我个人挺喜欢龙之谷(DN)的人物控制的(不是广告哈....),就是人物太萌了一点,动作、打击感都挺好的。
今天用Unity简单模仿了一下DN的人物控制,当然,游戏里面动作很多,我这里只做了简单的walk和run的测试哈,但是感觉也蛮舒服的,哈哈。
期待的效果:鼠标旋转控制视角位置,滚轮控制镜头缩放。点击一次W键为行走,快速点击两次为奔跑。
1.准给工作:
场景中,
一个Camera、一块地皮、一只Cube
2.镜头的缩放和旋转实现:
看下Camera的组件:
再看下Cube的组件:
mouselook和smoothfollow的脚本就不贴出来了,都有的。
为了方便,下面是NMove和TestMove的代码:
- using UnityEngine;
- using System.Collections;
- public class NMove : MonoBehaviour {
- //注意,开始之所以在滑动滚轮的时候,相机是抛物线的形式靠近/远离目标的,原因是,目标模型的中心点设置在了脚底。
- //解决方法:设置初始时,相机的高度与人物模型中心的高度一致,即可!
- public int MouseWheelSensitivity = 5; //鼠标敏感度
- public int MouseZoomMin = 2; //最小值
- public int MouseZoomMax = 10; //最大值
- public float normalDistance; //正常距离
- public GameObject Camera;
- smooth_follow CameraScript;
- // Use this for initialization
- void Start ()
- {
- CameraScript = Camera.GetComponent<smooth_follow>();
- }
- void LateUpdate()
- {
- if (Input.GetAxis("Mouse ScrollWheel") != 0) //转动了滚轮
- {
- Debug.Log(Input.GetAxis("Mouse ScrollWheel"));
- //Debug.Log(distance);
- if (normalDistance >= MouseZoomMin && normalDistance <= MouseZoomMax)
- {
- normalDistance -= Input.GetAxis("Mouse ScrollWheel") * MouseWheelSensitivity;
- }
- if (normalDistance < MouseZoomMin)
- {
- normalDistance = MouseZoomMin;
- }
- if (normalDistance > MouseZoomMax)
- {
- normalDistance = MouseZoomMax;
- }
- CameraScript.distance = normalDistance;
- }
- }
- }
- using UnityEngine;
- using System.Collections;
- public class TestMove : MonoBehaviour {
- public float speed = 1.0f;
- public GameObject camera;
- //当按下行走坐标后,物体旋转至camera的方向
- public float rospeed = 1.0f; //rotate speed
- // Update is called once per frame
- void Update () {
- if (Input.GetKey(KeyCode.W | KeyCode.S | KeyCode.A | KeyCode.D))
- {
- //按下了行走键,旋转
- transform.rotation = Quaternion.Slerp(transform.rotation,camera.transform.rotation ,Time.deltaTime*rospeed);
- transform.eulerAngles = new UnityEngine.Vector3(0,transform.eulerAngles.y,transform.eulerAngles.z);
- //notice only Quaternion have Slerp methods.
- }
- if (Input.GetKey(KeyCode.W))
- {
- this.transform.Translate(Vector3.forward*Time.deltaTime*speed);
- }
- if (Input.GetKey(KeyCode.S))
- {
- this.transform.Translate(Vector3.forward * Time.deltaTime * speed * -1);
- }
- if (Input.GetKey(KeyCode.D))
- {
- this.transform.Translate(Vector3.right * Time.deltaTime * speed);
- }
- if (Input.GetKey(KeyCode.A))
- {
- this.transform.Translate(Vector3.right * Time.deltaTime * speed * -1);
- }
- }
- }
OK,现在你的Cube角色已经活动自如了!
注意,我这里用Cube因为是标准的立方体,主要是为了方便。
3.添加你喜欢的人物模型,制作状态机,使Cube成为其父物体:
状态机:
下面是PlayerSM(state machine)的代码:
- using UnityEngine;
- using System.Collections;
- /// <summary>
- /// @author ZJC player state machine study note
- /// 问题:
- /// 1.如何实现对同一按键点击两次run,点击一次walk?设置一个信号signal进行区分.要注意按键的逻辑顺序问题,这是关键
- /// 2.人物转身的时候,有点斜着飘
- /// (恩,这个问题解决,就是girl的父物体,我用了一个标准的cube,这样cube旋转的时候,就不会有那种斜着旋转的效果了,girl也就不会了。
- /// </summary>
- public class PlayerSM : MonoBehaviour {
- private Animator animator;
- // 动画状态机参数Key
- private static readonly string ActionCMD = "ActionCMD";
- private static readonly string Run = "run";
- float timefirst = 0f; //记录按下W的时间
- float timesecond = 0f;
- int n = 0;
- bool runsignal = false;
- public float KeyTime = 0.3f;
- void Start()
- {
- animator = this.GetComponent<Animator>();
- }
- // Update is called once per frame
- void Update ()
- {
- AnimatorStateInfo stateinfo = animator.GetCurrentAnimatorStateInfo(0);
- if (Input.GetKey(KeyCode.W))
- {
- print("runsigl = "+runsignal);
- if ( !runsignal )
- {
- animator.SetInteger(ActionCMD, 1);
- }
- else
- {
- animator.SetInteger(Run, 1);
- animator.SetInteger(ActionCMD, 0);
- print("wwwww+runsigal = " + runsignal);
- }
- }
- if (Input.GetKeyDown("w") )
- {
- // print("up.....");
- // runsignal = false;
- if (n == 0)
- {
- timefirst = Time.time;
- n++;
- }
- else if (n == 1)
- {
- timesecond = Time.time;
- n = 0;
- }
- if (Mathf.Abs(timesecond - timefirst) <= KeyTime)
- {
- // print("wreff");
- animator.SetInteger(Run, 1);
- print("run = 1..........................");
- runsignal = true;
- }
- }
- if(!Input.anyKey) //只要按下了键(包括持续按键),就为真,否则为false
- {
- //参数清0
- animator.SetInteger(ActionCMD, 0);
- animator.SetInteger(Run, 0);
- runsignal = false;
- }
- }
- }
4.隐藏掉cube的mesh render.再测试,OK!
效果:鼠标位置控制旋转视角、滚轮控制视角缩放、点击一次W人物行走,快速点击两次奔跑,无按键为idle状态。