Unity实现宠物跟随移动

发表于2018-08-02
评论0 4.5k浏览
多数RPG游戏中都有宠物,如果确保主角移动过程中宠物会跟随着一起移动,下面就给大家介绍下实现宠物跟随移动的方法。

简单的跟随移动

玩家移动控制脚本: 
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMove : MonoBehaviour {
    // Use this for initialization
    void Start () {
    }
    // Update is called once per frame
    void Update () {
        float h = Input.GetAxis ("Horizontal");
        float v = Input.GetAxis ("Vertical");
        if(h!=0 || v!=0){
            transform.LookAt (transform.position+new Vector3(h,0,v));
            transform.Translate (transform.forward*Time.deltaTime*5f,Space.World);
        }
    }
}

跟对对象移动控制脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PetMove : MonoBehaviour {
    public Transform player;//主角
    public float speed=1f;//移动的阻尼,值越小,移动越平缓
    // Use this for initialization
    void Start () {
    }
    // Update is called once per frame
    void Update () {//如果主角和宠物直接的距离大于5,控制宠物跟随主角移动
        if(Vector3.Distance(player.position,transform.position)>5f){
            PetSmothFlow ();
            //to do。。播放移动动画
        }
        //to do。。播放站立动画
        //控制宠物的朝向
        transform.LookAt (player.position);
    }
    //控制宠物的位置平滑移动
    void PetSmothFlow(){
        transform.position=Vector3.Lerp (transform.position,player.position,Time.deltaTime*speed);
    }
}

宠物跟随移动

玩家移动控制脚本:
using UnityEngine;
using System.Collections;
public class PlayerMove : MonoBehaviour {
    public float speed = 8f;
    Animator anim;
    // Use this for initialization
    void Start () {
        anim = this.GetComponent<Animator>();
    }
    // Update is called once per frame
    void Update () {
        float h = Input.GetAxis("Horizontal");
        float v=Input.GetAxis("Vertical");
        if (Mathf.Abs(h) > 0 || Mathf.Abs(v) > 0)
        {
            transform.LookAt(transform.position + new Vector3(h, 0, v));
            transform.Translate(transform.forward * Time.deltaTime * speed, Space.World);
            anim.SetBool("Run", true);
        }
        else anim.SetBool("Run",false);
    }
}

跟对对象移动控制脚本:
using UnityEngine;
using System.Collections;
public class PetFlow : MonoBehaviour {
    public Transform player;
    public float maxDis = 5;
    Animator anim;
    private SmoothFollowerObj posFollow;//控制位置平滑移动
    private SmoothFollowerObj lookFollow;//控制朝向平滑转换
    public Vector3 positionVector;//角色位置移动的时候,方向向量
    public Vector3 lookVector;//角色朝向变化的时候,朝向向量
    private Vector3 lastVelocityDir;//上一次移动的方向
    private Vector3 lastPos;//之前移动的目标点位置
    // Use this for initialization
    void Start () {
        anim = this.GetComponent<Animator>();//获取动画控制器
        posFollow = new SmoothFollowerObj(0.5f, 0.5f);
        lookFollow = new SmoothFollowerObj(0.1f, 0.0f);
        posFollow.Update(transform.position, 0, true);//初始化负值
        lookFollow.Update(player.transform.position, 0, true);
        positionVector = new Vector3(0, 0.5f, 1.7f);
        lookVector = new Vector3(0, 0, 1.5f);
        lastVelocityDir = player.transform.forward;
        lastPos = player.transform.position;
    }
    // Update is called once per frame
    void Update () {
        float dis = Vector3.Distance(transform.position,player.position);
        if (dis > maxDis)//如果玩家和宠物之间的距离大于允许的最大距离,控制宠物向玩家移动
        {
            PetMoveFlow();//宠物移动的逻辑
            anim.SetBool("Run", true);
        }
        else {
            anim.SetBool("Run",false);
        }
        transform.LookAt(player.position,Vector3.up);
    }
    private void PetMoveFlow()
    {
        lastVelocityDir += (player.transform.position - lastPos) * 5;
        lastPos = player.transform.position;
        lastVelocityDir += player.transform.forward * Time.deltaTime;
        lastVelocityDir = lastVelocityDir.normalized;
        Vector3 horizontal = transform.position - player.transform.position;
        Vector3 horizontal2 = horizontal;
        Vector3 vertical = player.transform.up;
        Vector3.OrthoNormalize(ref vertical, ref horizontal2);
        if (horizontal.sqrMagnitude > horizontal2.sqrMagnitude) horizontal = horizontal2;
        transform.position = posFollow.Update(
            player.transform.position + horizontal * Mathf.Abs(positionVector.z) + vertical * positionVector.y,
            Time.deltaTime
        );
        horizontal = lastVelocityDir;
        Vector3 look = lookFollow.Update(player.transform.position + horizontal * lookVector.z - vertical * lookVector.y, Time.deltaTime);
        transform.rotation = Quaternion.FromToRotation(transform.forward, look - transform.position) * transform.rotation;
    }
     class SmoothFollowerObj
    {
        private Vector3 targetPosition;
        private Vector3 position;
        private Vector3 velocity;
        private float smoothingTime;
        private float prediction;
        public SmoothFollowerObj(float smoothingTime)
        {
            targetPosition = Vector3.zero;
            position = Vector3.zero;
            velocity = Vector3.zero;
            this.smoothingTime = smoothingTime;
            prediction = 1;
        }
        public SmoothFollowerObj(float smoothingTime, float prediction)
        {
            targetPosition = Vector3.zero;
            position = Vector3.zero;
            velocity = Vector3.zero;
            this.smoothingTime = smoothingTime;
            this.prediction = prediction;
        }
        // 更新位置信息
        public Vector3 Update(Vector3 targetPositionNew, float deltaTime)
        {
            Vector3 targetVelocity = (targetPositionNew - targetPosition) / deltaTime;//获取目标移动的方向向量
            targetPosition = targetPositionNew;
            float d = Mathf.Min(1, deltaTime / smoothingTime);
            velocity = velocity * (1 - d) + (targetPosition + targetVelocity * prediction - position) * d;
            position += velocity * Time.deltaTime;
            return position;
        }
        //根据传递进来的数据,重置本地参数
        public Vector3 Update(Vector3 targetPositionNew, float deltaTime, bool reset)
        {
            if (reset)
            {
                targetPosition = targetPositionNew;
                position = targetPositionNew;
                velocity = Vector3.zero;
                return position;
            }
            return Update(targetPositionNew, deltaTime);
        }
        public Vector3 GetPosition() { return position; }
        public Vector3 GetVelocity() { return velocity; }
    }
}

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引