我个人挺喜欢龙之谷(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; } } }TestMove.cs:
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状态。