首页 > 代码库 > Unity模拟龙之谷人物行走简单控制

Unity模拟龙之谷人物行走简单控制

我个人挺喜欢龙之谷(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状态。