NPC追随者 - 如何实现脚本

时间:2018-03-28 14:54:29

标签: c# unity3d

我的目标是让NPC关注ThePlayer。我有一个功能正常的NPCFollower脚本附加到一个角色,有两个动画,空闲和步行。 我想知道是否有人知道我如何使用'SimpleCharacterControl'script实现NPCFollower脚本,该脚本附加到带有多个动画的动画师的角色。我想呼吁两个动画,走路和闲置。我非常感谢你的帮助!

NPCFollow'脚本

public class NPCFollow : MonoBehaviour {

public GameObject ThePlayer;
public float TargetDistance;
public float AllowedDistance = 5;
public GameObject TheNPC;
public float FollowSpeed;
public RaycastHit Shot;


void Update () {
    transform.LookAt(ThePlayer.transform);
    if (Physics.Raycast(transform.position,transform.TransformDirection(Vector3.forward),out Shot))
    {
        TargetDistance = Shot.distance;
        if(TargetDistance >= AllowedDistance)
        {
            FollowSpeed = 0.02f;
            TheNPC.GetComponent<Animation>().Play("Walk");
        }



        else
        {
            FollowSpeed = 0;
            TheNPC.GetComponent<Animation>().Play("Idle");
        }
    }       
}

}

'SimpleCharacterControl'script

public class SimpleCharacterControl : MonoBehaviour {

private enum ControlMode
{
    Tank,
    Direct
}

[SerializeField] private float m_moveSpeed = 2;
[SerializeField] private float m_turnSpeed = 200;
[SerializeField] private float m_jumpForce = 4;
[SerializeField] private Animator m_animator;
[SerializeField] private Rigidbody m_rigidBody;

[SerializeField] private ControlMode m_controlMode = ControlMode.Direct;

private float m_currentV = 0;
private float m_currentH = 0;

private readonly float m_interpolation = 10;
private readonly float m_walkScale = 0.33f;
private readonly float m_backwardsWalkScale = 0.16f;
private readonly float m_backwardRunScale = 0.66f;

private bool m_wasGrounded;
private Vector3 m_currentDirection = Vector3.zero;

private float m_jumpTimeStamp = 0;
private float m_minJumpInterval = 0.25f;

private bool m_isGrounded;
private List<Collider> m_collisions = new List<Collider>();

private void OnCollisionEnter(Collision collision)
{
    ContactPoint[] contactPoints = collision.contacts;
    for(int i = 0; i < contactPoints.Length; i++)
    {
        if (Vector3.Dot(contactPoints[i].normal, Vector3.up) > 0.5f)
        {
            if (!m_collisions.Contains(collision.collider)) {
                m_collisions.Add(collision.collider);
            }
            m_isGrounded = true;
        }
    }
}

private void OnCollisionStay(Collision collision)
{
    ContactPoint[] contactPoints = collision.contacts;
    bool validSurfaceNormal = false;
    for (int i = 0; i < contactPoints.Length; i++)
    {
        if (Vector3.Dot(contactPoints[i].normal, Vector3.up) > 0.5f)
        {
            validSurfaceNormal = true; break;
        }
    }

    if(validSurfaceNormal)
    {
        m_isGrounded = true;
        if (!m_collisions.Contains(collision.collider))
        {
            m_collisions.Add(collision.collider);
        }
    } else
    {
        if (m_collisions.Contains(collision.collider))
        {
            m_collisions.Remove(collision.collider);
        }
        if (m_collisions.Count == 0) { m_isGrounded = false; }
    }
}

private void OnCollisionExit(Collision collision)
{
    if(m_collisions.Contains(collision.collider))
    {
        m_collisions.Remove(collision.collider);
    }
    if (m_collisions.Count == 0) { m_isGrounded = false; }
}

void Update () {
    m_animator.SetBool("Grounded", m_isGrounded);

    switch(m_controlMode)
    {
        case ControlMode.Direct:
            DirectUpdate();
            break;

        case ControlMode.Tank:
            TankUpdate();
            break;

        default:
            Debug.LogError("Unsupported state");
            break;
    }

    m_wasGrounded = m_isGrounded;
}

private void TankUpdate()
{
    float v = Input.GetAxis("Vertical");
    float h = Input.GetAxis("Horizontal");

    bool walk = Input.GetKey(KeyCode.LeftShift);

    if (v < 0) {
        if (walk) { v *= m_backwardsWalkScale; }
        else { v *= m_backwardRunScale; }
    } else if(walk)
    {
        v *= m_walkScale;
    }

    m_currentV = Mathf.Lerp(m_currentV, v, Time.deltaTime * m_interpolation);
    m_currentH = Mathf.Lerp(m_currentH, h, Time.deltaTime * m_interpolation);

    transform.position += transform.forward * m_currentV * m_moveSpeed * Time.deltaTime;
    transform.Rotate(0, m_currentH * m_turnSpeed * Time.deltaTime, 0);

    m_animator.SetFloat("MoveSpeed", m_currentV);

    JumpingAndLanding();
}

private void DirectUpdate()
{
    float v = Input.GetAxis("Vertical");
    float h = Input.GetAxis("Horizontal");

    Transform camera = Camera.main.transform;

    if (Input.GetKey(KeyCode.LeftShift))
    {
        v *= m_walkScale;
        h *= m_walkScale;
    }

    m_currentV = Mathf.Lerp(m_currentV, v, Time.deltaTime * m_interpolation);
    m_currentH = Mathf.Lerp(m_currentH, h, Time.deltaTime * m_interpolation);

    Vector3 direction = camera.forward * m_currentV + camera.right * m_currentH;

    float directionLength = direction.magnitude;
    direction.y = 0;
    direction = direction.normalized * directionLength;

    if(direction != Vector3.zero)
    {
        m_currentDirection = Vector3.Slerp(m_currentDirection, direction, Time.deltaTime * m_interpolation);

        transform.rotation = Quaternion.LookRotation(m_currentDirection);
        transform.position += m_currentDirection * m_moveSpeed * Time.deltaTime;

        m_animator.SetFloat("MoveSpeed", direction.magnitude);
    }

    JumpingAndLanding();
}

private void JumpingAndLanding()
{
    bool jumpCooldownOver = (Time.time - m_jumpTimeStamp) >= m_minJumpInterval;

    if (jumpCooldownOver && m_isGrounded && Input.GetKey(KeyCode.Space))
    {
        m_jumpTimeStamp = Time.time;
        m_rigidBody.AddForce(Vector3.up * m_jumpForce, ForceMode.Impulse);
    }

    if (!m_wasGrounded && m_isGrounded)
    {
        m_animator.SetTrigger("Land");
    }

    if (!m_isGrounded && m_wasGrounded)
    {
        m_animator.SetTrigger("Jump");
    }
}

}

1 个答案:

答案 0 :(得分:0)

1)获取对ThePlayer的引用(您希望其他对象遵循的任何对象)。 2)找到ThePlayer的方向。 3)在DistanceFromTarget的更新检查中

if (DistanceFromTarget <= distanceUwant)
{
  setMovingSpeed=0;
  playIdelAnimation();
}
else 
{
  setMovingSpeed= asmuchyouwant;
  playWalkAnimation();
}