Unity3d基础(1)角色自动寻路、方向键移动、第三人称相机



今天做了一个人物点击鼠标移动的Demo,还有方向键的移动。
    人物点击鼠标移动自然要用到NavMeshAgent寻路组件了:
    首先我先说说把人物素材导入进去遇到的问题:
    1.导入进去的时候人物模型是白的,没有皮肤,即使把材质球贴了也一样,这样我才发现是模型的缩放比例太小了,才0.01,正常是0.5,0.01导致了两个问题,第一,模型的材质贴图显示不出来,二,模型拖到场景视图上根本看不见。所以要记得改改缩放比例Scale Factor这个
    2.一开始我倒进来的动画类型是Generic,然后我在角色中添加动画组件,在代码中写播放动画,结果代码提示动画不存在。我就把模型和所有的动画都改成Legacy,结果是所有的动画都自动倒进Animation组件中去了,而且在代码中也能识别了,真不错.
      上网查了一下Unity 动画类型,才发现Legacy是老的动画系统,下面有一篇关于动画系统的分析写得不错,有空我再学习学习
http://www.360doc.com/content/13/1216/12/12282510_337556448.shtml
  
  接着说说,我在做人物自动寻路的问题:
   正确步骤是这样子的,对地板plane属性面板的static勾上,然后Layer 选择default(我这里选择的是第八层,随便取个名字abc 因为我在后面的寻路代码中加入了射线的参数mask==1<<8,这里的8是后面的第八层,后面我再解释),当然你选择default括号的不用再看了,只是如过要使用我的代码可能要注意一下了呵呵。。。。继续,然后直接bake一下,会生成蓝色的地板,提示你要保存场景,保存完了就地板的就制作好了。然后再给主角添加一个寻路组件NavMeshAgent组件,整个寻路步骤就此完成
   我遇到的问题是属性面板旁边的那个Navigation选项卡经常会不见了,只要在菜单栏windows上面选择Navigation就出现了。
人物自动寻路代码如下:
playerControl.cs:
using UnityEngine;
using System.Collections;

public class PlayerControl : MonoBehaviour
{
    //这个代表要寻路的主角
    NavMeshAgent m_player;
    //这个是主角的动作动画
    Animation m_animation;

    //主角在跑时候的速度
    public float speed;

    //照相机要跟上主角移动
    Transform m_Camera;

    public float m_MoveFactor = 4.0f;
    public float m_RotateFactor = 10.0f;
    Vector3 nowPosition;

    void Start()
    {
       //通过这个函数可以找到套在主角身上的所有组件,这次找的是寻路组件哈
        m_player = GetComponent();
        //获取主角身上的动画数组
        m_animation = animation;
       //获取照相机的位置-----transform是位置信息,可以平移,缩放,旋转。
        m_Camera = Camera.main.transform;
        //这个是我为了获取主角当前位置所设的
        nowPosition = transform.position;
    }

    void Update()
    {
        nowPosition = transform.position;
        //有任何键盘按下的时候会中断当前的寻路:原理很简单,只要把寻路目标换成主角当前的位置就好了
        if (Input.anyKeyDown)
        {
            m_player.SetDestination(nowPosition);
        }
       //主角如果到了目的地,播放待机动作
        if (m_player.remainingDistance == 0)
        {
            m_animation.CrossFade("idle");
        }
       否则,播放跑步动作
        else
        {
            m_animation.CrossFade("run");
        }
        //难点来了,鼠标为什么不能通过一个三维像两个直接捕获鼠标的点击位置:因为鼠标点击的坐标是屏幕坐标,这时要用射线做成空间坐标
        //左击鼠标开始移动
        if (Input.GetMouseButtonDown(0))
        {
            Debug.Log(" clickLeftMouseButton! ");

            Ray ray;
            RaycastHit hit;
           //这个mask就是我选择Layers改为第八层的原因
            LayerMask mask = 1 << 8;
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit, Mathf.Infinity, mask))
            {
                Debug.DrawLine(ray.origin, hit.point, Color.red, 2);

                m_player.SetDestination(hit.point);

            }

        }
       

    }
}



2.相机功能:
1.跟随主角移动;
2.  按住鼠标右键拖动能够移动过视图
3.滚动鼠标滚轮能够放大缩小游戏视图
4.用我的代码要改动一处, target = GameObject.Find("nanzhujueSCJ");红色的改成你的角色名称
代码如下
c1.cs
using UnityEngine;
using System.Collections;

[AddComponentMenu("Camera-Control/Mouse Look")]

public class c1 : MonoBehaviour
{



    public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }

    public RotationAxes axes = RotationAxes.MouseXAndY;

    public float sensitivityX = 15F;

    public float sensitivityY = 15F;



    public float minimumX = -360F;

    public float maximumX = 360F;



    public float minimumY = -85F;

    public float maximumY = 4F;



    public float rotationY = 0F;



    public GameObject target;



    public float theDistance = -10f;

    public float MaxDistance = -10f;

    public float ScrollKeySpeed = 100.0f;

    void Update()
    {
//这里的target要改成你主角的名字
        target = GameObject.Find("nanzhujueSCJ");

        // 滚轮设置 相机与人物的距离.

        if (Input.GetAxis("Mouse ScrollWheel") != 0)
        {

            theDistance = theDistance + Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * ScrollKeySpeed;

        }

        // 鼠标中间滚动得到的值是不确定的,不会正好就是0,或 -10,当大于0时就设距离为0,小于MaxDistance就设置为MaxDistance

        if (theDistance > 0)

            theDistance = 0;

        if (theDistance < MaxDistance)

            theDistance = MaxDistance;
//按下鼠标右键
        if (Input.GetMouseButton(1))
        {

            transform.position = target.transform.position;

            if (axes == RotationAxes.MouseXAndY)
            {

                float rotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * sensitivityX;



                rotationY += Input.GetAxis("Mouse Y") * sensitivityY;

                rotationY = Mathf.Clamp(rotationY, minimumY, maximumY);

                transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);

            }

            else if (axes == RotationAxes.MouseX)
            {

                transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityX, 0);

            }

            else
            {

                rotationY += Input.GetAxis("Mouse Y") * sensitivityY;

                rotationY = Mathf.Clamp(rotationY, minimumY, maximumY);

                transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, 0);

            }

            SetDistance();

        }

        else
        {

            transform.position = target.transform.position;

            SetDistance();

        }

    }



    void Start()
    {

        if (rigidbody)
        {

            rigidbody.freezeRotation = true;

            transform.position = target.transform.position;

        }

    }



    //设置相机与人物之间的距离

    void SetDistance()
    {

        transform.Translate(Vector3.forward * theDistance);

    }

}
3.人物方向键移动,这里做了优化,同时兼容两个按键,旋转的时候显得很自然过度
代码如下:
playerKeyMove.cs:


using UnityEngine;
using System.Collections;

public class playerKeyMove: MonoBehaviour
{

    //动画对象
    Animation m_Animation;
   
    //移动的速度
    public float speed;
    //平移对象(照相机)
    Transform m_Camera;

   
    //移动大小
    public float m_MoveFactor = 4.0f;
    //旋转大小
    public float m_RotateFactor = 10.0f;

    void Start()
    {
        //获取装有寻路功能的对象
        m_NavmeshAgent = GetComponent();
        //实例化animation动画
        m_Animation = animation;
        //平移对象相机是主相机的平移
        m_Camera = Camera.main.transform;
    }
   
    // Update is called once per frame
    void Update()
    {

        //这部分内容是主角键盘移动
        //如果WSAD键松开的时候是处于正常状态
        if (Input.GetKeyUp(KeyCode.W) || Input.GetKeyUp(KeyCode.S) || Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.D)) {
            m_Animation.CrossFade("idle");
        }
        //当W键按下的时候,又有其他键按下的时候主角应该出现旋转
        if (Input.GetKey(KeyCode.W))
        {
            //按下左键的时候逆时针旋转45度
            if (Input.GetKey(KeyCode.A)) {
                Move(-45.0f);
            }
            else if (Input.GetKey(KeyCode.D)){
                Move(45.0f);
            }
            else
                //这个键值不旋转
                Move(0.0f);
        }
        else if (Input.GetKey(KeyCode.S))
        {
            if (Input.GetKey(KeyCode.A)) {
                Move(-135.0f);
            }
            else if (Input.GetKey(KeyCode.D)){
                Move(135.0f);
            }
            else
                Move(-180.0f);
        }
        else if (Input.GetKey(KeyCode.A))
        {
            Move(-90.0f);
        }
        else if (Input.GetKey(KeyCode.D))
        {
            Move(90.0f);
        }
        else if(Input.GetKey(KeyCode.Space))
        {
            //m_Animation.CrossFade("attack01");
            Debug.Log("攻击");
        }    
    }
    //这个函数的功能是实现
    void Move(float delta)
    {
        //Quaternion是四元数,先计算角度angle是主相机的欧拉角
        //transform.eulerAngles(x,y,z)表示分别绕x,y,z旋转的角度
            float angle = m_Camera.eulerAngles.y + delta;
            Quaternion rotate = Quaternion.Euler (0, angle, 0);
        //主角开始移动,移动的距离是旋转角度rotate*3维向量向前Vector.forward*一秒Time.deltaTime*移动的速度m_MoveeFactor
            m_NavmeshAgent.Move(rotate * Vector3.forward * Time.deltaTime * m_MoveFactor);
        //主角旋转transform.rotation=
        //Quaternion.Lerp意思是四元数的插值
            transform.rotation = Quaternion.Lerp(transform.rotation, rotate, Time.deltaTime * m_RotateFactor);
        //播放跑的动作
        //Animation.CrossFade 淡入淡出动画
            m_Animation.CrossFade("run");   
    }
}


这篇文章我发布在另外一个博客上:http://www.unitymanual.com/blog.html
点击阅读

你可能感兴趣的:(Unity游戏堂)