抱歉抱歉,这两天都没时间做,今天就要修改《无眼地牢》玩家反馈的BUG了。
真的很感谢这两天反馈的玩家,都超级认真啊!如果真能上steam的话,一定给大家key作为感谢!!!!
然后昨天睡觉前我做完了《Wall》控制玩家移动的功能。
想的是按下方向键,就可以走一步这样。
首先,我做了一个单例化的类,用来监测玩家的按键。
所有玩家要按的键的监测,都在这个类中进行管理和处理。
在Unity中实现单例化真的太方便了,所以基本上会经常重复使用的、但又只需要1个实例的类,我都会做成单例模式。
代码如下:
using System.Collections;using System.Collections.Generic;using UnityEngine;namespace Com.XiMiGua.Wall{//用于处理监测用户的按键输入的静态类//单例化public class StaticInput : MonoBehaviour{#region 单例化public static StaticInput Instance;void Awake(){Instance = this;}#endregion#region 变量[HideInInspector]public bool InputUpArrow; //是否输入方向键的 –上键[HideInInspector]public bool InputDownArrow; //是否输入方向键的 –下键[HideInInspector]public bool InputLeftArrow; //是否输入方向键的 –左键[HideInInspector]public bool InputRightArrow; //是否输入方向键的 –右键#endregion#region Unity回调函数void Start(){InputUpArrow = false;InputDownArrow = false;InputLeftArrow = false;InputRightArrow = false;}void Update(){InputUpArrow = Input.GetKeyDown(KeyCode.UpArrow);InputDownArrow = Input.GetKeyDown(KeyCode.DownArrow);InputLeftArrow = Input.GetKeyDown(KeyCode.LeftArrow);InputRightArrow = Input.GetKeyDown(KeyCode.RightArrow);}#endregion}}
我们有了监测用户按下按键的脚本了之后,就可以开始处理移动啦!
移动的话,因为Unity 中移动的方式太多了。
我开始用的是角色控制器,但是效果并不好,它会频繁穿墙,而且没有重力。
然后 我又试了下刚体,刚体移动有重力,但是因为我们是按一下移动一格,移动速度太快了!所以也会穿墙。
最后就用Transform进行移动,这样简单粗暴,而且后面还能用DoTween进行插值动画。
但是Transform没有重力,所以再添加一个刚体组件,为角色增加重力(不用刚体组件,也可以自己写射线检测,但是为了快速做出来,就直接使用刚体组件啦~)。
然后Transform是不管速度快不快,都会穿墙的!因为利用Transform进行移动会无视碰撞器。
所以我准备在角色移动到一个新的地方的时候,向四个方向发送射线,这样进行射线检测,看看能不能走动。
所以我们需要一个脚本来保存射线检测的结果。
代码如下(这个类我也做成单例模式了):
using System.Collections;using System.Collections.Generic;using UnityEngine;namespace Com.XiMiGua.Wall{/// <summary>/// 这个类用于存储,判断角色是否能够移动 的结果/// 单例化/// </summary>public class StaticMoveJudge : MonoBehaviour{#region 单例化public static StaticMoveJudge Instance;void Awake(){Instance = this;}#endregion#region 变量[HideInInspector]public bool IsUp;//是否能够向前进?[HideInInspector]public bool IsDown;//是否能够向后退?[HideInInspector]public bool IsLeft;//是否能够向左走?[HideInInspector]public bool IsRight;//是否能够向右走?#endregion#region Unity回调函数void Start(){IsUp = true;IsDown = true;IsLeft = true;IsRight = true;}#endregion}}
然后我把这两个脚本,挂到一个空物体上,把空物体命名为StaticClass,专门拿来挂单例化的脚本用的。
现在,就该做射线检测了。
但是我又突然觉得射线检测太麻烦,干脆用触发器来代替射线检测!
我真的是特别喜欢使用触发器来代替射线检测的。
那么我现在在角色的前后左右4个方向(角色只能朝4个方向进行移动),各放置一个Collider。
这个Collider的范围要比一个格子小,不然可能会碰撞到下下个格子上的碰撞器。
然后勾选Collider组件上的Trigger选项,把碰撞器变成一个触发器。
在Unity里,Collider(碰撞器)和Trigger(触发器)真的是太太太太常用了。
他们之间唯一的区别就是,碰撞器就像墙一样,会挡住玩家。触发器则不会。
比如,我们现在搭建个场景给大家演示一下:
如果地面是碰撞器,当正方体因为重力自由下落的时候,当碰到了地面,小球就会像真的碰撞到了地面一样,停下来
但如果地面是触发器,那么则不会产生碰撞,方块会穿过地面,继续下落
我们现在是希望这个Collider能穿过物体,然后如果它穿过了物体,就代表它的前面有障碍物,就不能朝那个方向移动。
所以,我们用触发器正合适。
现在的状态就像这样,玩家身上有一个大的碰撞器,用于和地面发生碰撞,不穿模的。
然后前后左右各有一个小的触发器,用于判断这个方向是否能移动。
我们现在给向前的触发器身上添加一个脚本叫做MoveIsUp.cs,用来管理是否能向前进行移动。
代码如下:
using System.Collections;using System.Collections.Generic;using UnityEngine;namespace Com.XiMiGua.Wall{/// <summary>/// 这个类用于,判断角色是否能够向前移动/// </summary>public class MoveIsUp : MonoBehaviour{void OnTriggerEnter(Collider other)//当有障碍物的时候{StaticMoveJudge.Instance.IsUp = false;//不能向前走}void OnTriggerExit(Collider other){StaticMoveJudge.Instance.IsUp = true;}}}
大概是这样的:当有物体进入碰撞器的时候,就代表前面有障碍物,不能前进。
当有物体离开碰撞器的是,代表前面没有障碍物了,可以前进了。
凑是这么简单哈哈哈哈!
然后剩下的3个方向也用同样的方式来做。
但是现在还有一个问题!就是,我们的玩家身上也有碰撞器,虽然我们可以写if语句来做区分。但是我最爱用的还是给不同的物体添加不同的层,然后指定哪些层跟那些层可以发生碰撞,这样大大提高了性能!
现在是这样的,我们把触发器设置为Move层,把地板和墙壁等障碍物设置为Plane层,让Move层只和Plane层发生碰撞。
最最最后就是移动的代码了!
为了让大家看的清除,下面的移动代码只实现向前移动。
using UnityEngine;using System.Collections;using JacobGames.SuperInvoke;namespace Com.XiMiGua.Wall{//这个类用于控制角色进行移动public class PlayerMove : MonoBehaviour{#region 变量public float moveDistance = 0.9f;//移动的距离,默认为0.9#endregion#region Unity回调函数void Update(){SetMoveDirection();//监测用户输入,并设置角色移动的方向}#endregion#region 私有方法/// <summary>/// 监测用户输入,并设置角色移动的方向,并移动/// </summary>private void SetMoveDirection(){//Up向前走(如果用户输入了方向键的右键,就设置为往前走)if (StaticInput.Instance.InputRightArrow){Move(Direction.Up);//调用移动的方法}}/// <summary>/// 用于让角色移动/// </summary>/// <param name=”direction”>移动的方向</param>private void Move(Direction direction){Vector3 newPosition = transform.position;//如果是向前走,并且前面没有障碍物if (direction == Direction.Up && StaticMoveJudge.Instance.IsUp){newPosition.x -= moveDistance;}//移动transform.position = newPosition;}#endregion}}
现在角色身上是这样的:
有一个碰撞体(BoxCollider),一个刚体(Rigidbody),以及一个我们刚刚写的PlayerMove脚本。
现在碰到了墙就过不去了呢!完美!哈哈哈哈或!!!
感觉这一篇会让很多人感觉Unity很难,但是如果不使用游戏引擎的话,开发这些功能需要更加更加久的时间。
游戏引擎可以让我们节省80%的开发时间和精力。
感觉看不懂是因为,完全没有Unity的基础知识,如果我们下定决心,带上热爱慢慢学,大概1周就能开始做自己的游戏!
好啦!我要去改无眼地牢的BUG啦!我们明天见~