Unity3D 1D动画行为混合树 第三人称人物控制器

相机控制(Cameramanager)

using UnityEngine;
namespace dgl {

    public class CameraManager : MonoBehaviour {
        public bool lockon = false;
        public float followSpeed = 9;
        public float mouseSpeed = 2;
        public float controllerSpeed = 7;
        public Transform target;
        [HideInInspector]
        public Transform pivot;
        [HideInInspector]
        public Transform camTrans;

        float turnSmoothing = .1f;
        public float minAngle = -35;
        public float maxAngle = 35;

        float smoothX;
        float smoothY;
        float smoothXVelocity;
        float smoothYVelocity;
        public float lookAngle;
        public float tilAngle;

        public static CameraManager singleton;
        public void Init (Transform t) {
            target = t;
            camTrans = Camera.main.transform;
            pivot = camTrans.parent;
        }
        public void Tick (float d) {
            float h = Input.GetAxis ("Mouse X");
            float v = Input.GetAxis ("Mouse Y");

            float c_h = Input.GetAxis ("RightAxis X");
            float c_v = Input.GetAxis ("RightAxis Y");

            float targetSpeed = mouseSpeed;

            if (c_h != 0 || c_v != 0) {
                h = c_h;
                v = c_v;
                targetSpeed = controllerSpeed;
            }
            FollowTarget (d);
            HandleRotations (d, v, h, targetSpeed);
        }

        void FollowTarget (float d) {
            float speed = d * followSpeed;
            Vector3 targetPosition = Vector3.Lerp (transform.position, target.position, speed);
            transform.position = targetPosition;
        }
        void HandleRotations (float d, float v, float h, float targetSpeed) {
            if (turnSmoothing > 0) {
                smoothX = Mathf.SmoothDamp (smoothX, h, ref smoothXVelocity, turnSmoothing);
                smoothY = Mathf.SmoothDamp (smoothY, v, ref smoothYVelocity, turnSmoothing);
            } else {
                smoothX = h;
                smoothY = v;
            }
            if ( lockon)
            {
                
            }
            lookAngle+=smoothX*targetSpeed;
            transform .rotation=Quaternion.Euler(0,lookAngle,0);

            tilAngle -=smoothY*targetSpeed;
            tilAngle=Mathf.Clamp(tilAngle,minAngle,maxAngle);
            pivot.localRotation=Quaternion.Euler(tilAngle,0,0);
        }
        /// <summary>
        /// Awake is called when the script instance is being loaded.
        /// </summary>
        void Awake () {
            singleton = this;
        }
    }
}

 

状态控制(StateManager)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class StateManager : MonoBehaviour {
    [Header ("Init")]
    public GameObject activeModel;
    [Header ("Input")]
    public float vertical;
    public float horiziontal;
    public float moveAmount;
    public Vector3 moveDir;
    [Header ("Stats")]
    public float moveSpeed = 2;
    public float runSpeed = 3.5f;
    public float rotateSpeed = 5;
    public float toGround = .5f;
    [Header ("States")]
    public bool run;
    public bool onGround;
    public bool lockOn;
    [HideInInspector]
    public Animator animator;
    [HideInInspector]
    public Rigidbody rigid;
    [HideInInspector]
    public float delta;
    [HideInInspector]
    public LayerMask ignoreLayers;
    // Start is called before the first frame update
    void Start () {
        Init ();
    }
    // Update is called once per frame
    void Update () {

    }
    public void Init () {
        SetupAnimator ();
        rigid = GetComponent<Rigidbody> ();
        rigid.angularDrag = 999;
        rigid.drag = 4;
        rigid.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
        gameObject.layer = 8;
        ignoreLayers = ~(1 << 9);

        animator.SetBool ("onGround", true);
    }
    void SetupAnimator () {
        if (activeModel == null) {
            animator = GetComponent<Animator> ();
            if (animator == null) {
                Debug.Log ("nO MODEL");
            } else {
                activeModel = animator.gameObject;
            }

        }
        if (animator == null)
            animator = activeModel.GetComponent<Animator> ();
    }
    public void Tick (float d) {
        delta = d;
        onGround = OnGround ();
        animator.SetBool ("onGround", onGround);
    }
    void HandleMovementAnimations () {
        animator.SetBool ("run", run);
        animator.SetFloat ("vertical", moveAmount, .4f, delta);
    }
    public bool OnGround () {
        bool r = false;
        Vector3 origin = transform.position + (Vector3.up * toGround);
        Vector3 dir = -Vector3.up;
        float dis = toGround + .3f;
        RaycastHit hit;
        if (Physics.Raycast (origin, dir, out hit, dis, ignoreLayers)) {
            r = true;
            Vector3 targetPosition = hit.point;
            transform.position = targetPosition;
        }
        return r;
    }
    public void FixedTick (float d) {
        delta = d;

        rigid.drag = (moveAmount > 0 || onGround == false) ? 0 : 4;

        float targetSpeed = moveSpeed;

        if (run) {
            targetSpeed = runSpeed;
        }

        if (onGround) {
            rigid.velocity = moveDir * (targetSpeed * moveAmount);
        }

        if (run) {
            lockOn = false;
        }

        if (!lockOn) {
            Vector3 targetDir = moveDir;
            targetDir.y = 0;
            if (targetDir == Vector3.zero) {
                targetDir = transform.forward;
            }

            Quaternion tr = Quaternion.LookRotation (targetDir);
            Quaternion targetRotation = Quaternion.Slerp (transform.rotation, tr, delta * moveAmount * rotateSpeed);
            transform.rotation = targetRotation;
        }

        HandleMovementAnimations ();
    }

}

 

输入封装(InputHandler)

using System.Collections;
using System.Collections.Generic;
using dgl;
using UnityEngine;
public class InputHandler : MonoBehaviour {
    float vertical = 0;
    float horiziontal = 0;
    bool runInput;
    StateManager states;
    CameraManager cameraManager;

    float delta;
    // Start is called before the first frame update
    void Start () {
        states = GetComponent<StateManager> ();
        states.Init ();
        cameraManager = CameraManager.singleton;
        cameraManager.Init (this.transform);
    }

    // Update is called once per frame
    void Update () {
        delta = Time.deltaTime;
        states.Tick (delta);
    }
    private void FixedUpdate () {
        delta = Time.fixedDeltaTime;
        GetInput ();
        UpdateState ();
        states.FixedTick (delta);
        cameraManager.Tick (delta);
    }
    void GetInput () {
        vertical = Input.GetAxis ("Vertical");
        horiziontal = Input.GetAxis ("Horizontal");
        runInput = Input.GetButton ("RunInput");
    }
    void UpdateState () {
        states.vertical = vertical;
        states.horiziontal = horiziontal;

        Vector3 v = states.vertical * cameraManager.transform.forward;
        Vector3 h = states.horiziontal * cameraManager.transform.right;

        states.moveDir = (v + h).normalized;
        float m = Mathf.Abs (horiziontal) + Mathf.Abs (vertical);
        states.moveAmount = Mathf.Clamp01 (m);

        if (runInput) {

            states.run = (states.moveAmount > 0);
            if (states.moveAmount > 0)
                states.run = true;

        } else {
            states.run = false;
        }
    }

}

//TODO视角锁定 二维混合树动画  


版权声明:本文为qmAlin原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。