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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章