123 lines
4.0 KiB
C#
123 lines
4.0 KiB
C#
|
|
using System.Collections;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
public class NpcMovementController : MonoBehaviour {
|
|||
|
|
|
|||
|
|
[SerializeField] private SpriteRenderer spriteRenderer;
|
|||
|
|
[SerializeField] private Animator animator;
|
|||
|
|
[SerializeField] private Rigidbody2D rigidBody;
|
|||
|
|
[SerializeField] private float walkSpeed;
|
|||
|
|
[Range(0f, 1f)] [SerializeField] private float walkProbability;
|
|||
|
|
[Range(0f, 3f)] [SerializeField] private float smoothTime;
|
|||
|
|
|
|||
|
|
[SerializeField] private float minTimeIdle;
|
|||
|
|
[SerializeField] private float maxTimeIdle;
|
|||
|
|
[SerializeField] private float minTimeWalk;
|
|||
|
|
[SerializeField] private float maxTimeWalk;
|
|||
|
|
|
|||
|
|
public Vector2 boundsX;
|
|||
|
|
|
|||
|
|
public bool isFacingRight;
|
|||
|
|
public bool isWalking;
|
|||
|
|
private Vector2 targetVelocity;
|
|||
|
|
private Vector2 referenceVelocity = Vector2.zero;
|
|||
|
|
|
|||
|
|
private Vector2 myBounds;
|
|||
|
|
|
|||
|
|
// Start is called before the first frame update
|
|||
|
|
void Awake() {
|
|||
|
|
animator = gameObject.GetComponent<Animator>();
|
|||
|
|
rigidBody = gameObject.GetComponent<Rigidbody2D>();
|
|||
|
|
isFacingRight = true;
|
|||
|
|
isWalking = false;
|
|||
|
|
StartCoroutine("IdleWalkCoroutine");
|
|||
|
|
|
|||
|
|
myBounds = new Vector2(transform.position.x - boundsX.x, transform.position.x + boundsX.y);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void FixedUpdate() {
|
|||
|
|
// If you're about to walk off a ledge, don't.
|
|||
|
|
bool isMoving = Mathf.Abs(rigidBody.velocity.x) > 0.001;
|
|||
|
|
bool isMovingRight = rigidBody.velocity.x > 0;
|
|||
|
|
if (isMoving && !CheckBounds(isMovingRight)) {
|
|||
|
|
rigidBody.velocity = new Vector2(0f, rigidBody.velocity.y);
|
|||
|
|
targetVelocity = new Vector2(0f, rigidBody.velocity.y);
|
|||
|
|
} else if (Mathf.Abs(rigidBody.velocity.y) < 0.01f) {
|
|||
|
|
Vector2 newVelocity = new Vector2(Vector2.SmoothDamp(rigidBody.velocity, targetVelocity, ref referenceVelocity, smoothTime).x,
|
|||
|
|
rigidBody.velocity.y);
|
|||
|
|
rigidBody.velocity = newVelocity;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
animator.SetFloat("Speed", Mathf.Abs(rigidBody.velocity.x));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private bool TryToWalk(bool right, bool chase = false) {
|
|||
|
|
if (CheckBounds(right)) {
|
|||
|
|
if (right) {
|
|||
|
|
targetVelocity = new Vector3(walkSpeed, 0, 0);
|
|||
|
|
} else {
|
|||
|
|
targetVelocity = new Vector3(-1 * walkSpeed, 0, 0);
|
|||
|
|
}
|
|||
|
|
if (isFacingRight != right) {
|
|||
|
|
Flip();
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private bool CheckBounds(bool right) {
|
|||
|
|
if ((right && transform.position.x > myBounds.y) ||
|
|||
|
|
(!right && transform.position.x < myBounds.x)) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private IEnumerator IdleWalkCoroutine() {
|
|||
|
|
while (true) {
|
|||
|
|
if (ShouldWalk() && !isWalking) {
|
|||
|
|
// Walk in a random direction.
|
|||
|
|
isWalking = true;
|
|||
|
|
if (Random.Range(0f, 1f) < 0.5f) {
|
|||
|
|
// Walk left.
|
|||
|
|
if (!TryToWalk(false)) {
|
|||
|
|
TryToWalk(true);
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
// Walk right.
|
|||
|
|
if (!TryToWalk(true)) {
|
|||
|
|
TryToWalk(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
yield return new WaitForSeconds(RandomWalkSeconds());
|
|||
|
|
} else {
|
|||
|
|
// Idle.
|
|||
|
|
isWalking = false;
|
|||
|
|
targetVelocity = Vector3.zero;
|
|||
|
|
yield return new WaitForSeconds(RandomIdleSeconds());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private bool ShouldWalk() {
|
|||
|
|
return Random.Range(0f, 1f) < walkProbability;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private float RandomIdleSeconds() {
|
|||
|
|
return Random.Range(0f, 1f) * (maxTimeIdle - minTimeIdle) + minTimeIdle;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private float RandomWalkSeconds() {
|
|||
|
|
return Random.Range(0f, 1f) * (maxTimeWalk - minTimeWalk) + minTimeWalk;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void Flip() {
|
|||
|
|
isFacingRight = !isFacingRight;
|
|||
|
|
Vector3 scale = transform.localScale;
|
|||
|
|
scale.x *= -1;
|
|||
|
|
transform.localScale = scale;
|
|||
|
|
}
|
|||
|
|
}
|