Unity ARPG类游戏 动画、移动、镜头脚本

改进版

输入控制

using UnityEngine;

namespace script
{
    public class PlayerInput : MonoBehaviour
    {
        protected float InputH;
        protected float InputV;

        //控制角色的速度
        protected float InputSpeed;
        protected bool InputRun;
        protected bool InputJump;
        //是否可移动
        protected bool MoveAble;
        
        // Use this for initialization
        protected virtual void Start()
        {
            MoveAble = true;
            InputJump = false;
        }
        

        // Update is called once per frame
        protected virtual void Update()
        {

            //要在Update里检测,FixedUpdate可能会错过为GetKeyDown为true的帧
            if (Input.GetKeyDown(KeyCode.Mouse0))
            {
                MoveAble = false;
            }

            InputH = Input.GetAxis("Horizontal");
            InputV = Input.GetAxis("Vertical");
            SquareToCircle();

            InputSpeed = Mathf.Sqrt(InputH * InputH + InputV * InputV);
            
            if (Input.GetKey(KeyCode.LeftShift))
            {
                InputRun = true;
            }
            else
            {
                InputRun = false;
            }
            if (Input.GetKeyDown(KeyCode.Space))
            {
                InputJump = true;
            }
            else if (Input.GetKeyUp(KeyCode.Space))
            {
                InputJump = false;
            }
        }

        /**
         * 直角坐标转圆形坐标
         */
        private void SquareToCircle()
        {
            InputH = InputH * Mathf.Sqrt(1 - InputV * InputV / 2.0f);
            InputV = InputV * Mathf.Sqrt(1 - InputH * InputH / 2.0f);
        }
    }
}

动画控制器

using UnityEngine;
using Random = UnityEngine.Random;

namespace script
{
    /**
    * 动画控制器
    */
    public class AnimController : PlayerInput
    {
        
        protected bool isHit;
        
        private bool isAttack;
        
        private bool attackFlag;

        private float time;
        private int jumpBool;
        private int speedFloat;
        private int attackBool;
        private float animSpeed;

        protected Camera MainCamera;
        private Animator animator;

        protected virtual void Awake()
        {
            animator = GetComponent<Animator>();
        }

        // Use this for initialization
        protected override void Start()
        {
            base.Start();
            //获取动画变量的Hash值,提高效率
            jumpBool = Animator.StringToHash("Jump");
            speedFloat = Animator.StringToHash("Speed");
            attackBool = Animator.StringToHash("Attack");
            MainCamera = Camera.main;
            time = 0;
            MoveAble = true;
        }

        /**
     * 播放等待动画
     */
        private void PlayWaitAnim()
        {
            if (Input.anyKey)
            {
                time = 0;
            }
            else
            {
                time += Time.deltaTime;
                //30秒后,随机播放等待动画
                if (time > 30)
                {
                    var animCode = Random.Range(1, 5);
                    animator.Play("WAIT0" + animCode, -1);
                    time = 0;
                }
            }
        }

        public void ClearSignalAttack()
        {
            MoveAble = true;
            attackFlag = false;
            animator.SetBool(attackBool,false);
        }
        /**
     * 受到攻击动画播放结束回调
     */
        public void OnOver()
        {
            isHit = false;
        }

        // Update is called once per frame
        protected override void Update()
        {
            base.Update();
            
            PlayWaitAnim();

            //要在Update里检测,FixedUpdate可能会错过为GetKeyDown为true的帧
            if (Input.GetKeyDown(KeyCode.Mouse0))
            {
                /*if (!isHit)
            {
                isHit = true;
                if (Random.Range(0, 2) == 0)
                {
                    animator.Play("DAMAGED00", -1);
                }
                else
                {
                    animator.Play("DAMAGED01", -1);
                }
            }*/
                attackFlag = true;
                animator.Play("ATTACK",-1);
                animator.SetBool(attackBool,true);
                MoveAble = false;
            }

            animSpeed = InputRun ? InputSpeed * 2.0f : InputSpeed;

            animator.SetFloat(speedFloat, Mathf.Lerp(animator.GetFloat(speedFloat), animSpeed, 0.2f));

            animator.SetBool(jumpBool,InputJump);
        }
    }
}

角色控制器

using UnityEngine;

namespace script
{
    /**
    * 角色控制器
    */
    public class ThirdPersonController : AnimController
    {
        //走动速度
        public float walkSpeed = 1.0f;

        //跑动速度
        public float runSpeed = 5.0f;
        public float gravity = 9.8f;
        public float jumpSpeed = 10f;

        //转向速度
        public float turnSpeed = 5f;
        public GameObject model;

        private float speed;

        private CharacterController characterController;
        private Vector3 moveDirection;
        private Transform camTrans;
        private Vector3 camDirection;
        private Vector3 forward;


        protected override void Awake()
        {
            base.Awake();
            characterController = GetComponent<CharacterController>();
        }
        // Use this for initialization

        protected override void Start()
        {
            base.Start();
            camTrans = MainCamera.transform;
        }

        // Update is called once per frame
        protected override void Update()
        {
            base.Update();

            //当起跳后,前进速度被保存,用于表现跳跃后的惯性前进
            //所以moveDirection的速度应在if里
            if (characterController.isGrounded)
            {
                //先判断是否前进,提高性能
                if (MoveAble && InputSpeed > 0.1)
                {
                    //以摄像机为参照系
                    camDirection = camTrans.forward * InputV + camTrans.right * InputH;
                    camDirection.y = 0;
                    camDirection.Normalize();
                    
                    //角色转向摄像机的方向
                    forward = Vector3.Slerp(
                        transform.forward,
                        camDirection,
                        turnSpeed * Time.deltaTime);

                    transform.forward = forward;
                    moveDirection.Set(forward.x, 0, forward.z);

                    speed = InputRun ? runSpeed : walkSpeed;
                    //向角色的前方前进,转向更加自然
                }
                else
                {
                    speed = 0;
                }

                moveDirection *= speed;
                if (InputJump)
                {
                    moveDirection.y = jumpSpeed;
                }
            }

            // 重力计算
            moveDirection.y = moveDirection.y - (gravity * Time.deltaTime);
            // 移动角色
            characterController.Move(moveDirection * Time.deltaTime);
        }
    }
}

摄像机控制器

using UnityEngine;

namespace script
{
    public class MoveCamera : MonoBehaviour
    {
        //观察目标
        public Transform target;

        //观察距离
        public float distance = 2f;

        //视角x轴旋转速度
        public float speedX = 24;

        //视角y轴旋转速度
        public float speedY = 12;

        //旋转角度限制
        public float maxLimitY = 65;
        public float minLimitY = -75;

        //鼠标缩放距离限制
        public float maxDistance = 10;

        public float minDistance = 1.5F;

        //鼠标缩放速率
        public float zoomSpeed = 2F;

        //旋转角度
        private float mX = 0.0F;
        private float mY = 0.0F;
    
        //控制鼠标的显示
        public bool lockCursor = true;

        private Quaternion mRotation;

        void Start()
        {
            //初始化旋转角度
            Vector3 angles = transform.eulerAngles;
            mX = angles.x;
            mY = angles.y;

            if (target == null)
            {
                //自动查找以player为标签的对象
                GameObject player = GameObject.FindGameObjectWithTag("Player");
                if (player != null)
                {
                    target = player.transform;
                }
                else
                {
                    //禁用脚本
                    enabled = false;
                }
            }

            speedX *= 0.1f;
            speedY *= 0.1f;

            if (lockCursor)
            {
                Cursor.visible = false;
            }
        }

        void Update()
        {
            //获取鼠标输入
            mX += Input.GetAxis("Mouse X") * speedX;
            mY -= Input.GetAxis("Mouse Y") * speedY;

            mX = ClampAngle(mX);
            //范围限制
            mY = Mathf.Clamp(mY, minLimitY, maxLimitY);
            //计算旋转
            //我们可以通过Quaternion.Euler()方法将一个Vector3类型的值转化为一个四元数
            //,进而通过修改Transform.Rotation来实现相同的目的
            mRotation = Quaternion.Euler(mY, mX, 0);
            
            //设置相机的方向
            //不建议设置插值,应该立即更新
            transform.rotation = mRotation;

            //鼠标滚轮缩放
            distance -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeed;
            distance = Mathf.Clamp(distance, minDistance, maxDistance);

            //重新计算位置,设置相机位置
            transform.position = mRotation * (new Vector3(0, 1, -distance)) + target.position;
        }

        //角度限制
        private float ClampAngle(float angle)
        {
            if (angle < 0) angle += 360;
            if (angle > 360) angle -= 360;
            return angle;
        }
    }
}

未改进版

摄像机控制脚本

自由旋转,跟随角色,距离缩放

不建议使用差值,使用差值会导致快速旋转时镜头到角色的距离发生明显改变

using UnityEngine;

public class MoveCamera : MonoBehaviour
{
    //观察目标
    public Transform target;

    //观察距离
    public float distance = 2f;

    //视角x轴旋转速度
    public float speedX = 24;
    //视角y轴旋转速度
    public float speedY = 12;

    //旋转角度限制
    public float maxLimitY = 65;
    public float minLimitY = -75;

    //鼠标缩放距离限制
    public float maxDistance = 10;

    public float minDistance = 1.5F;

    //鼠标缩放速率
    public float zoomSpeed = 2F;

    //旋转角度
    private float mX = 0.0F;
    private float mY = 0.0F;

    //是否启用差值
    public bool isNeedDamping = false;

    //平滑度
    public float damping = 10F;

    //控制鼠标的显示
    public bool lockCursor = true;

    private Quaternion mRotation;

    void Start()
    {
        //初始化旋转角度
        Vector3 angles = transform.eulerAngles;
        mX = angles.x;
        mY = angles.y;
        
        if (target == null)
        {
            //自动查找以player为标签的对象
            GameObject player = GameObject.FindGameObjectWithTag("Player");
            if (player != null)
            {
                target = player.transform;
            }
            else
            {
                //禁用脚本
                enabled = false;
            }
        }
        
        speedX *= 0.1f;
        speedY *= 0.1f;
        
        if (lockCursor)
        {
            Cursor.visible = false;
        }
    }

    void LateUpdate()
    {
        //获取鼠标输入
        mX += Input.GetAxis("Mouse X") * speedX;
        mY -= Input.GetAxis("Mouse Y") * speedY;
        
        mX = ClampAngle(mX);
        //范围限制
        mY = Mathf.Clamp(mY, minLimitY, maxLimitY);
        //计算旋转
        //我们可以通过Quaternion.Euler()方法将一个Vector3类型的值转化为一个四元数
        //,进而通过修改Transform.Rotation来实现相同的目的
        mRotation = Quaternion.Euler(mY, mX, 0);
        //设置相机的方向
        //根据是否插值采取不同的角度计算方式
        if (isNeedDamping)
        {
            transform.rotation = Quaternion.Lerp(
                transform.rotation, mRotation, Time.deltaTime * damping);
        }
        else
        {
            transform.rotation = mRotation;
        }

        //鼠标滚轮缩放
        distance -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeed;
        distance = Mathf.Clamp(distance, minDistance, maxDistance);

        //重新计算位置
        Vector3 mPosition = mRotation * (new Vector3(0, 1, -distance)) + target.position;

        //设置相机位置
        if (isNeedDamping)
        {
            transform.position = Vector3.Lerp(transform.position, mPosition, Time.deltaTime * damping);
        }
        else
        {
            transform.position = mPosition;
        }
    }

    //角度限制
    private float ClampAngle(float angle)
    {
        if (angle < 0) angle += 360;
        if (angle > 360) angle -= 360;
        return angle;
    }
}

动画控制脚本

跑、走、停、跳

using UnityEngine;
using Random = UnityEngine.Random;

/**
 * 动画控制器
 */
public class AnimController : MonoBehaviour
{
    protected float inputH;
    protected float inputV;
    
    //用来控制动画状态机的走、跑、停
    protected int animSpeed;

    private float time;
    private int jumpBool;
    private int speedInt;
    private bool isHit;
    protected Camera mainCamera;
    private Animator animator;

    // Use this for initialization
    protected virtual void Start()
    {
        animator = GetComponent<Animator>();
        //获取动画变量的Hash值,提高效率
        jumpBool = Animator.StringToHash("Jump");
        speedInt = Animator.StringToHash("Speed");
        mainCamera = Camera.main;
        time = 0;
    }

    /**
     * 播放等待动画
     */
    private void PlayWaitAnim()
    {
        if (Input.anyKey)
        {
            time = 0;
        }
        else
        {
            time += Time.deltaTime;
            //30秒后,随机播放等待动画
            if (time > 30)
            {
                var animCode = Random.Range(1, 5);
                animator.Play("WAIT0" + animCode, -1);
                time = 0;
            }
        }
    }

    /**
     * 受到攻击动画播放结束回调
     */
    public void OnOver()
    {
        isHit = false;
    }

    // Update is called once per frame
    protected virtual void Update()
    {
        PlayWaitAnim();

        //要在Update里检测,FixedUpdate可能会错过为GetKeyDown为true的帧
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            if (!isHit)
            {
                isHit = true;
                if (Random.Range(0, 2) == 0)
                {
                    animator.Play("DAMAGED00", -1);
                }
                else
                {
                    animator.Play("DAMAGED01", -1);
                }
            }
        }

        inputH = Input.GetAxis("Horizontal");
        inputV = Input.GetAxis("Vertical");

        animSpeed = IsMove() ? 1 : 0;

        if (animSpeed == 1 && Input.GetKey(KeyCode.LeftShift))
        {
            animSpeed = 2;
        }

        animator.SetInteger(speedInt, animSpeed);
        if (Input.GetKeyDown(KeyCode.Space))
        {
            animator.SetBool(jumpBool, true);
        }else if (Input.GetKeyUp(KeyCode.Space))
        {
            animator.SetBool(jumpBool, false);
        }
        
        
    }

    /**
     * 是否正在移动
     */
    private bool IsMove()
    {
        return !isHit && (inputH > 0.1 || inputV > 0.1 || inputH < -0.1 || inputV < -0.1);
    }
}

角色控制脚本

镜头控制转向

using System;
using UnityEngine;

/**
 * 角色控制器
 */
public class ThirdPersonController : AnimController
{
    //走动速度
    public float walkSpeed = 1.0f;
    //跑动速度
    public float runSpeed = 5.0f;
    //转向速度
    public float turnSpeed = 1.5f;

    private float speed;

    private CharacterController characterController;
    private Rigidbody rig;

    // Use this for initialization

    protected override void Start()
    {
        base.Start();
        characterController = GetComponent<CharacterController>();
        speed = walkSpeed;
        rig = GetComponent<Rigidbody>();
    }

    // Update is called once per frame
    protected override void Update()
    {
        base.Update();
        //先判断是否前进,提高性能
        if (animSpeed > 0)
        {
            Vector3 moveDirection = new Vector3(inputH, 0, inputV);
            //以摄像机为参照系
            moveDirection = mainCamera.transform.TransformDirection(moveDirection);
            moveDirection.y = 0;
            //角色转向摄像机的方向
            this.transform.rotation = Quaternion.Slerp(
                this.transform.rotation,
                Quaternion.LookRotation(moveDirection),
                turnSpeed * Time.deltaTime);

            speed = animSpeed == 1 ? walkSpeed : runSpeed;
            //向角色的前方前进,转向更加自然
            characterController.SimpleMove(
                transform.TransformDirection(Vector3.forward) * speed);
        }
    }
}

你可能感兴趣的:(Unity ARPG类游戏 动画、移动、镜头脚本)