搭建场景

使用资源商店的素材搭建基本的场景,如图所示:

值得一提的是:
在材质下我们要选择合适的纹理细分程度,细分程度越高纹理越细腻,在项目中我们的墙面和地板使用了不同的细分程度。

地面使用xy等比例细分,因为我们的地面是我们等比放大的,墙面则是我们拉伸横轴放大的,所以我们细分时要注意使用拉伸x轴的方式

编写Human类

human是我们的角色类,处理玩家控制,电脑同步等情况。
Human类型可分为以下几种:
+ BaseHuman 基础类型的human 被子类继承重写
+ CtrlHuman 玩家控制类型的human 是本地玩家所操控的游戏对象
+ SyncHuman 电脑同步类型的human 是电脑将其他玩家信息反馈出来的载体

BaseHuman

using UnityEngine;
using UnityEngine.Serialization;

namespace _Scripts
{
    /// <summary>
    /// 基础角色类
    /// </summary>
    public class BaseHuman : MonoBehaviour
    { 
        //参数

        [Header("移动速度")]
        public float speed=1.2f;
        [Header("描述")]
        public string desc = "";

        protected bool IsMoving;
        private Vector3 _targetPosition;


        //组件
        private Animator _animator;
        private static readonly int Moving = Animator.StringToHash("isMoving");


       protected void MoveTo(Vector3 pos)
       {
           _targetPosition = pos;
           IsMoving = true;
           _animator.SetBool(Moving,true);
       }

       protected void MoveUpdate()
       {
           if (!IsMoving)
           {
               return;
           }

           var pos = transform.position;

           transform.position=Vector3.MoveTowards(pos,_targetPosition,speed*Time.deltaTime);
           transform.LookAt(_targetPosition);
           if (Vector3.Distance(pos,_targetPosition)<=0.05f)
           {
               IsMoving = false;
               _animator.SetBool(Moving,false);
           }
       }
        protected void Start()
        {
            _animator = GetComponent<Animator>();
        }


        protected void Update()
        {
            MoveUpdate();
        }
    }
}

CtrlHuman

using UnityEngine;
using UnityEngine.Serialization;

namespace _Scripts
{
    /// <summary>
    /// 基础角色类
    /// </summary>
    public class BaseHuman : MonoBehaviour
    { 
        //参数

        [Header("移动速度")]
        public float speed=1.2f;
        [Header("描述")]
        public string desc = "";

        protected bool IsMoving;
        private Vector3 _targetPosition;


        //组件
        private Animator _animator;
        private static readonly int Moving = Animator.StringToHash("isMoving");


       protected void MoveTo(Vector3 pos)
       {
           _targetPosition = pos;
           IsMoving = true;
           _animator.SetBool(Moving,true);
       }

       protected void MoveUpdate()
       {
           if (!IsMoving)
           {
               return;
           }

           var pos = transform.position;

           transform.position=Vector3.MoveTowards(pos,_targetPosition,speed*Time.deltaTime);
           transform.LookAt(_targetPosition);
           if (Vector3.Distance(pos,_targetPosition)<=0.05f)
           {
               IsMoving = false;
               _animator.SetBool(Moving,false);
           }
       }
        protected void Start()
        {
            _animator = GetComponent<Animator>();
        }


        protected void Update()
        {
            MoveUpdate();
        }
    }
}

SyncHuman

namespace _Scripts
{
    /// <summary>
    /// 同步角色
    /// </summary>
    public class SyncHuman:BaseHuman
    {
        new void Start()
        {
            base.Start();
        }

        new void Update()
        {
            base.Update();
        }
    }
}

其完成后将CtrlHuman挂载在玩家对象上,并创建相关的动画状态机。

其实现后运行效果如图:

技术总结

在玩家移动中主要使用了以下的几个重要API:

射线检测

使用了Camera.main获得主摄像机,使用摄像机的ScreenPointToRay()获得鼠标点击位置
理由RaycastHit 将射线碰撞信息返回。

移动

使用了vector3下的MoveTowards方法,此方法可实现一个点向另一个点移动。