Unity3d实现的十字路口的模拟(二)

ok,下面就进入我们的讲解工作啦,我的这个的讲解应该是比较适合初学者的,所以会有一些啰嗦什么的就请大家见谅啦!

想必来看这个blog的,大家都已经知道了Unity3D的一些基本的操作了吧!这里我也就不一一赘述了,毕竟不是什么一个Unity的课程。ok,我这里用的是Unity3D5,然后下面来说一下关于这个小程序的小车的建立。

一开始的时候,我只是在网上找了一些相关的3d模型然后直接拉入Unity中(注意一定要是fbx格式的哦),我当时天真的不断地调节车速和轮子的转动当然就是在脚本里写一些平移和旋转的代码啦,虽然离近了看还是不真实,但是至少我们的车轮还是动了是吧~但是,当遇到拐弯的时候,我就遇到了瓶颈,如果一个正常的车,它的拐弯一定是车头引导的啊,但是我现在无论怎么变也只是看着车头和车尾一起平移过去的,于是我开始查找,找了很多资料(或许也是刚学,没有输入正确的关键词吧),终于让我发现了一个unity自带的一个函数库——WheelCollider,这个类真的是天生就是为赛车游戏开发而设立的啊!这里的运动完全是通关后轮的驱动还带动前轮(当然也可以四驱),而拐弯也就是前轮的带动,实在是完美的解决了我的问题,但是问题也就随之而来了,那就是怎么用这个?我找了好多的资料,都是说把这个库拖入轮子上就好,但是,我拖入后根本就是无法和预想的一样啊,后来我好不容易发现了一个教学视频真的是帮了我的大忙!我觉得文字还是不够直观,所以我觉得大家还是去看看这个视频,真的很有用,那位老师教的很好~这里给出一个链接,大家可以去看看(一共分为了五个你可以找一下车轮的设置在哪里)可以到这里学习:http://www.tudou.com/programs/view/CaBwp072c2Y/

ok 下面就说一下具体的实现吧,话说让车子拐弯而又不脱离公路哪里我还真的是研究了好半天,怎么也找不到方法,终于想起了下载Unity自带的例子,于是我就去找,还真的找到了一个有关汽车ai的例子,也是千辛万苦的读下来,但是其中很多算法还是不明白,但是我发现我已经找到了一个方法了,而且是不需要ai的。受到例子的启示,我本来是想直接还是用Unity的一个WayPoint Circuit的但是这个是建立环路的,而我的想法是建立一条单向道路,所以我就防着这样的思路,建立了一个我的汽车行进的路线,如下图所示:


看到啦那个way_1那些标志了吗?这就是我们的路标点,其实就是一个个的Cube然后把他们保留Collider但是把形状渲染取消,所以就成了一个个透明的小盒子,给他们加入触发器,当校车碰到这个标志点的时候就让小车指向下一个标志点,到达最后一个标志点的时候把这个校车Destory,由于我们的路标点很少只有五个,如果让校车驶向一个个的路标点的话那么必然就会导致小车行驶的十分生硬,所以受到了Unity自带例子的启发我给没一个小车前面加入了一个透明的引导球这样的话让引导球驶向标志点,小车追着引导球(当然小车和引导球之间保持一样的速度),引导球就起到了一个缓冲的作用,保证了小车的圆滑的拐弯。下面是一个小车整体的组成:


看到了左边的小球了吗?那个除了引导的作用还有探测前方是否有车的情况,如果它有碰撞的话那么就会出现一个汽车被它后面的另一个汽车离得好远撞飞了,所以不可能让它具有碰撞性,所以,我们就应该给他设置为触发器方式,但是再次运行的时候你就会发现,这个引导球不见了,小车也不按照既定的路线行驶了,我通过种种的实验发现需要把小球的重力取消就ok!


这个是小球的检视面板看那个IsTriger打了勾就代表这个小球无碰撞,是一种触发器模式,而那个Use Gravity没有打勾就是没有重力的影响。而那个ballmove就是我们要写的函数,小球有两个任务一个是引导,一个是检测车辆,下面给出代码:

#pragma strict
private var waypoint:Transform[]=new Transform[5];
private var move_speed:float;
private var nextpoint:int;
var car:GameObject;
private var carbody:Rigidbody;
private var path:GameObject;
private var current:int;//记录当前point位置
private var turn_brake:int;//转弯刹车
private var stop_brake:int;//停车刹车
private var way_name:String;
private var go:int;
private var last_colllider:String;
function Start () {
  turn_brake=20;//30
  stop_brake=10000;
  nextpoint=0;
  carbody=car.GetComponent("Rigidbody");
  way_name=createcar.path_name;//从生成车辆函数得到当前车的位置并且选择与之对应的道路
  Debug.Log(way_name);
  if(way_name==null){//第一辆车本就有的不用生成所以对应name是null
    way_name="left_right";
  }
  switch(way_name){//针对不同位置生成的车对应不同的行进方式
    case "left_right":
    path=GameObject.Find("way_left_turnright");
    break;

    case "left_left":
    path=GameObject.Find("way_left_turnleft");
    break;
    
    case "left_go":
    path=GameObject.Find("way_left_go");
    break;
    
    case "left_hurry":
    path=GameObject.Find("way_left_hurry");
    break;
    
    case "bot_right":
    path=GameObject.Find("way_bot_right");
    break;
    
    case "bot_left":
    path=GameObject.Find("way_bot_left");
    break;
    
    case "bot_go":
    path=GameObject.Find("way_bot_go");
    break;
    
    case "bot_hurry":
    path=GameObject.Find("way_bot_hurry");
    break;
    
    case "top_right":
    path=GameObject.Find("way_top_right");
    break;
    
    case "top_left":
    path=GameObject.Find("way_top_left");
    break;
    
    case "top_go":
    path=GameObject.Find("way_top_go");
    break;
    
    case "top_hurry":
    path=GameObject.Find("way_top_hurry");
    break;
    
    case "right_right":
    path=GameObject.Find("way_right_right");
    break;
    
    case "right_left":
    path=GameObject.Find("way_right_left");
    break;
    
    case "right_go":
    path=GameObject.Find("way_right_go");
    break;
    
    case "right_hurry":
    path=GameObject.Find("way_right_hurry");
    break;
    
  }
  //childCount获得子物体的数量
  for(var i:int =0;i<path.transform.childCount;i++){//遍历路径的父集遍历集合把对应的point点放入我们的位置点数组中
    //Debug.Log(path.transform.GetChild(i).name);
    waypoint[i]=path.transform.GetChild(i);
  } 
}

function Update () {
  move_speed=carbody.velocity.magnitude;
  //Debug.Log("ball:"+move_speed);
  //改变小球的移动方向
  transform.forward=waypoint[nextpoint].position-transform.position;
  transform.Translate(0,0,move_speed*Time.deltaTime);
}

function lastcollider(name:String){
   Debug.Log("last coiilder:"+name);
   last_colllider=name;
}

function OnTriggerEnter(go:Collider){
//碰撞到point后转向下一个point
if(go.transform.name=="way_1"||go.transform.name=="way_2"||go.transform.name=="way_3"||go.transform.name=="way_4"||go.transform.name=="way_5"||go.transform.name=="stop_line"||go.transform.name=="Terrain"){
   counterway(go);
 }else if(transform.name=="cop_target"&&go.transform.name=="cop_collider"){//警车自己不要把自己弄停
   
 }else if(go.transform.name=="cop_target"||go.transform.name=="target"){
 
 }
 else if(go.transform.name!=lastcollider){
  Debug.Log("car_stop:"+go.transform.name);
  gameObject.SendMessageUpwards("isgo",1);
 }
}
function OnTriggerExit (other : Collider ) {
 // Debug.Log("exit");
  gameObject.SendMessageUpwards("isgo",0);
}

function counterway(go:Collider){
 if(nextpoint<waypoint.Length&&go.transform.IsChildOf(path.transform)){//因为有很多引导块,所以这里片段一下各自的路线,不要
 // 误走过了其他的路径块而导致计数的增加
   nextpoint++;
  }
 //右转遇到第二个标志点就减速
  if(way_name=="left_right"||way_name=="right_right"||way_name=="top_right"||way_name=="bot_right"){
  if(nextpoint==2){
    //Debug.Log("slow");
    gameObject.SendMessageUpwards("isbrake",turn_brake);
   }else{
    gameObject.SendMessageUpwards("isbrake",0);
   }
  }
  if(nextpoint==waypoint.Length){
   //Debug.Log("destory");
   Destroy(car);
  }
}
这里都有相应额注释我相信大家应该都可以看懂,其实代码并不难,重要的是一个解决问题的方式,ok小球和路径的建立就说到这里~

对了,想必大家也都看到了我有很多需要确定字符串的地方例如:way_name=="left_right"其实这里的字符串是要和建立物体的命名取得一致的,如下图给一个例子:


ok,今天这一节就讲到这里啦~

发布了40 篇原创文章 · 获赞 38 · 访问量 20万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章