Unity3d使用鼠标点击控制人物走动无效的问题
最近在自学Unity3d,在学到使用鼠标点击控制人物走动时,按照API上面将代码写好,如下:
void Update () {
// _clickListener.Update();
if (Input.GetMouseButtonUp (0)) {
ClickOn(Input.mousePosition);
}
}
void ClickOn(Vector2 pos)
{
if (player == null)
return;
Ray ray = this.GetComponent<Camera>().ScreenPointToRay(pos);
RaycastHit[] hits = Physics.RaycastAll(ray);
foreach (RaycastHit hit in hits){
BoxCollider bc = hit.collider as BoxCollider;
Debug.Log("bc.name is " + bc.name);
Debug.Log("bc.name is Contains floor " + bc.name.Contains("floor"));
if (bc != null && bc.name.Contains("floor") && player != null){
player.GetComponent<Player>().WalkTo(hit.point);
break;
}
}
}
检查下,没什么错误,Unity3d,点击运行,满以为接下来可以美滋滋的用鼠标控制人物走动了,想想还有点小激动呢!结果点击鼠标,毫无响应!!!!
what fuck?
代码咋回事?写错了吗,于是又反复的检查了一下代码,确认是没问题的。代码既然是没问题,但是又没有达到相应的功能,到底怎么回事呢?
遇到这样的情况第一想到的是肯定是有哪段代码没有执行,从以上代码来看,只有3个地方涉及到了判断逻辑,分别是:if (Input.GetMouseButtonUp (0)) 和foreach (RaycastHit hit in hits) 以及 if (bc != null && bc.name.Contains(“floor”) && player != null)。
先说第一个if (Input.GetMouseButtonUp (0)) :
这是用来判断是否点击了鼠标左键的判断,如果鼠标左键被点击,那么Input.GetMouseButtonUp (0)返回的则是true;
在以上的代码上的对应地方加上打印,最终代码如下:
if (Input.GetMouseButtonUp (0)) {
Debug.Log("the Mouse button has been press");
ClickOn(Input.mousePosition);
}
OK,运行,鼠标左键点击,发现Unity控制台打印为:
确实收到了鼠标的点击事件,那么确认第一个判断正确的可以pass掉,接下来看第二个逻辑foreach (RaycastHit hit in hits)
这句逻辑是用从射线碰撞点的数组中(具体可以百度)进行遍历的数组,在foreach (RaycastHit hit in hits) 里面加个打印,如下:
foreach (RaycastHit hit in hits){
Debug.Log("hits has been in ");
BoxCollider bc = hit.collider as BoxCollider;
Debug.Log("bc.name is Contains floor " + bc.name.Contains("floor"));
if (bc != null && bc.name.Contains("floor") && player != null){
player.GetComponent<Player>().WalkTo(hit.point);
break;
}
}
运行,没有执行打印。所以说明foreach语句里面的循环没有被执行,所以说明hits的数组长度为0.
再看:
Ray ray = this.GetComponent<Camera>().ScreenPointToRay(pos);
RaycastHit[] hits = Physics.RaycastAll(ray);
如果hits长度为0,则只能说明 Physics.RaycastAll(ray);拿到的数据为空。
为什么这句会拿到空,首先了解Physics.RaycastAll(ray)该方法return一个数组。ray代表射线,即拿到射线上的所有碰撞点,如果获取的数组为0.则毫无意义是因为没有碰撞器造成的。
搞明白这个问题后,继续回去检查GameObject的Component看有没有添加碰撞器。果然还没加,是这样的:
没有加就加一个,点击“Add Component” 加一个,如下图:
添加好之后,保存。继续运行,点击鼠标还是不动。。。。,几乎要放弃的,但是程序员有程序员的倔强。之前两个都解决了,所以再检查第三个 if (bc != null && bc.name.Contains(“floor”) && player != null),继续加Debug日志,发现bc.name.Contains(“floor”)这一句一直返回false,说明碰撞点的对象名字不包含"floor"。找到对应的gameObject,如下图:
默认的名字都不含有"floor",好吧 改名字呗!不用全部改,只用将地板的模型gameObject改成含有"floor"即可,比如我的,就只改了3个:
改完之后,运行,完美,可以走动了!
第一次写CSDN还不会传动态度,呵呵!
最后说一下,这些素材的都是从网上下载下来导入到工程里面的,里面很多默认的东西没有创建或改名,刚学习接触Unity3d,跟着教程视频,视频讲解老师略过了一些步骤后,就会发现自己没法实现视频上的效果,唉。。。没基础就是不行,好在有因为有其他编程语言的基础,有程序员的职业技能,哈哈,不错就是调试。emmm,仅以此文献给在编程领域摸滚打爬的程序员们,共勉!!!