Let'Go
1、讓一個物體圍繞某一點旋轉,有幾種方法?分別是什麼?旋轉函數transform.Rotate()來實現。
transform的RotateAround(vector3 postion,vector3 axis,float angle)函數
性能開銷由小到大排序
sphere collider , capsule collider , box collider ,Mesh collider
通過點積Vector3.Dot,可以計算兩個向量的夾角的。 Vector3.Cross 可以求兩個向量的叉積。
Vector3.Dot(transform.forward, target.position)
返回值為正時,目標在自己的前方,反之在自己的後方
判斷目標在自己的左右方位可以使用下面的方法:
Vector3.Cross(transform.forward, target.position).y
返回值為正時,目標在自己的右方,反之在自己的左方
通過點積可以計算兩個向量的夾角,叉積可以判斷目標在自己的方位。向量單位化後可以在遊戲中用來計算怪物視野張角;玩家視野張角;NPC視野張角等,完成巡邏索敵等一些功能。
voidStart ()
{
float a = 600.0f;
float b = 1.0f - 80.0f /100.0f;
float c = a * b;
int d = (int)c;
Debug.Log (a);
Debug.Log (b);
Debug.Log (c);
Debug.Log (d);
}
變量「d」的輸出結果為多少?為什麼?如果解決?
首先,變量「d」的輸出結果為119。
先解釋為什麼:在程序中精確計算中使用浮點數是非常危險的,儘管C#在浮點數運算時採取了很多措施使得浮點數運算的結果看起來是非常正常的。但實際上如果不清楚浮點數的特性而貿然使用的話(浮點數由於是計算機內部求補運算而進行的,因此可能存在誤差,將造成非常嚴重的隱患。而且在精度損失的時候,不會報告任何的錯誤,也不會有任何的異常產生~
小數多位後容易出現誤差,使用double會看得更多有效數字,但依然會有誤差,最後真正強轉為int的實際上是一個199.9……無限接近於200的數,這個時候,應該改變計算公式。或者把最後的intd = (int)c;改為更高精度的decimal。即可正常。
最後,所有的浮點型變量都存在精度損失的問題!而decimal是一個不折不扣的浮點型,不論它精度有多高,精度損失依然存在!如做大數據的百度,谷歌,財政等,肯定很多時候都要考慮這種問題。
修改腳本中的RenderQueue值。
使用另外一個攝像機,顯示特效。
修改粒子特效的Shader中的RendererQueue值。
結合其他設置,還可以通過3D空間中的Z軸調整
6、當一個細小的高速物體撞向另一個較大的物體時,會出現什麼情況?如何避免?穿透(碰撞檢測失敗)
射線檢測
碰撞體變大
FixedUpdate更新時間修改
代碼限制,加大計算量提前計算好下一個位置。
Awake——>Start——>Update
腳本自帶函數執行順序如下:將下面腳本掛在任意物體運行即可得到
Awake ->OnEable-> Start ->FixedUpdate-> Update -> LateUpdate ->OnGUI ->Reset -> OnDisable->OnDestroy
8、數列 1,1,2,3,5,8,13... 第 n 位數是多少 ? 用 C# 遞歸算法實現public int function(intn)
{
if(n == 1 || n == 2)
return 1;
else
return function(n - 1) + function(n - 2);
}
9、當遊戲中需要頻繁創建一個物體對象時,我們需要怎麼做來節省內存?
使用pool對象池。
使用AssetBundle也可以降低一定內存。
10、Unity動態加載資源有幾種方法,分別是什麼?
通過Resources模塊,調用它的load函數:可以直接load並返回某個類型的Object,前提是要把這個資源放在Resource命名的文件夾下,Unity不關有沒有場景引用,都會將其全部打入到安裝包中。
通過bundle的形式:即將資源打成 asset bundle 放在伺服器或本地磁碟,然後使用WWW模塊get 下來,然後從這個bundle中load某個object。
通過AssetDatabase.loadasset :這種方式只在editor範圍內有效,遊戲運行時沒有這個函數,它通常是在開發中調試用的
11、如何實現磁鐵效果?比如酷跑遊戲中,獲得磁鐵道具後,自動吸附附近金幣的效果
獲得磁鐵效果後,主要流程可以分為3步:
首先判斷金幣是否進入磁鐵有效範圍(圓半徑,距離,矩形,collider觸發器等方式都可以)
接著可以使用差值運算方法,Lerp方法或ITween等插件或者類似方法對金幣做一個緩動效果吸附的動畫,
最後判斷動畫到達目標點後(碰撞器,觸發器,計時等)進行銷毀加分等處理即可。
①在玩家身上相同的坐標位置創建一個空的gameobject作為自物體,添加圓形或者球形碰撞器(根據實際要求2D或者3D)來選擇,勾選istrigger作為觸發器,觸發器的範圍即為磁鐵吸附範圍,添加剛體,取消勾選useGravity,gameobject.setActive(false);
②當玩家獲得磁鐵道具後,控制該gameobject.setActive(true);
③在金幣上掛載腳本:
using UnityEngine;
using System.Collections;
public class TestForTrigger : MonoBehaviour {
public bool isAdsorbed = false;
private GameObject player;
public float speed = 1f;
void Awake () {
player = GameObject.FindGameObjectWithTag("Player");
}
void Update () {
if (isAdsorbed) {
speed += Time.deltaTime;
transform.Translate(Vector3.Normalize(player.transform.position - this.transform.position) * speed * Time.deltaTime);
}
}
void OnTriggerEnter(Collider other) {
if (other.tag=="Player") {
Destroy(this.gameObject);
}
}
}
最簡單的是設置Time.timeScale = 0,即可讓遊戲暫停,也可以使用Time.timeScale來做遊戲的 1倍2倍整體加速,但要記住無論Time.timeScale等於多少Update和LateUpdate都會去執行。
所以這兩個方法裡面需要自己用代碼控制。而且如果遊戲暫停以後想在暫停界面上繼續播放一些不受Time.timeScale影響的動畫或者粒子特效之類的,那麼我們就需要用到Time.realtimeSinceStartup去單獨恢復他們,還有聲音部分也需要單獨恢復timeScale。
最大的影響是,在timeScale=0時無法實現暫停菜單的動畫以及各種漂亮的點擊效果。
如果只想暫停某部分,或者為了更多需求和可擴展性,還是需要自己寫個相關的Manager來手動管理遊戲的暫停和開始。
13、Animator Controller中參數類型bool和trigger的區別是什麼?分別在何種情況下使用?
animator的trigger變量只能賦值,是一種觸發變量,觸發之後會自動關閉掉,沒辦法獲取當前狀態。
比如xxxx.animator.settrigger("Attack");在執行這一句時才是true ,但是執行後馬上自動的變為false。適合用在單次動作或者連續不同動作使用,比如三國無雙系列的攻擊和蓄力攻擊。
bool跟trigger不同在於觸發之後會一直執行,而且可以獲取當前狀態。適合用在長時間持續動作,比如行走跑步。
無論碰撞的兩個物體是利用碰撞器,還是利用觸發器,都必須帶有碰撞器組件Collider(Rigidbody2D),其中一個物體還必須帶有Rigidbody(Rigidbody2D)剛體。
人物控制器組件自身包含碰撞,另外一個物體帶有Collider就可以發生碰撞。
或者掛上腳本,自行用代碼去計算碰撞範圍也是可行的,比如AABB。
對象池用於需要被反覆調用的資源,以減少內存消耗和卡頓等現象,FPS遊戲中包括要常被大量複製的對象:子彈,敵人,濺血特效,彈坑以及任何重複出現的對象。
16、Lightmapping是什麼?為什麼要使用?
光照貼圖。使用Lightmapping預先模擬燈光帶來的效果,會帶來性能上的大大提升,手機上更明顯。當然會損失畫面效果,具體還是看項目需求。最簡單的直接在3dmas或maya裡面烘培完貼圖頂點色也行。
與Lightmapping相關的LightProbes也偶爾會使用,
用烘焙出來的假光在動態的物體或角色沒有受光會很突兀,顯得很戳。想要動態物體也有這樣的效果就需要用到LightProbes。
17、在塔防遊戲中,如何讓塔指向進入攻擊範圍的敵人並射擊?請簡述程序流程
先判斷NPC是否進入攻擊範圍(圓半徑,距離,矩形,collider觸發器等)。
根據塔的種類進行不同處理:
單目標攻擊:記錄第一個進入範圍的NPC,使用Lookat或者差值運算讓塔面向目標,然後利用ITween播放子彈動畫,目標為NPC,進行鎖定射擊。
範圍群體目標攻擊:記錄所有在塔範圍的NPC,存入List集合,每次攻擊遍歷集合併重複調用前面提到的單目標攻擊的方法。
指向性飛行道具:用碰撞器或觸發器,直接對NPC進行碰撞檢測即可。
18、Unity中,控制3D人物模型位移方式有幾種?Animator組件的Apply Root Motion的作用是?
1、this.m_transform.position= pos;在Update函數中調用
2、transform.Translate(Vector3direction)
3、CharacterController.Move(),CharacterController.simplemove()
4、Rigidbody.MovePosition();Rigidbody.velocity= Vector3.forward * MoveSpeed; Rigidbody.AddForce();
5、Vector3.MoveToward 當前的地點移向目標
如果勾選了Animator組件中的ApplyRoot Motion選項
角色的Transform將不能通過腳本來直接賦值,而是通過動畫的運動的來改變的
如果我們不勾選,我們就可以用腳本改變角色的Tranform
準備好序列幀動畫的素材,可以是單張也可以是圖集(需要設置Multiple模式在Sprite Editor切割)。
然後使用Animation進行動畫製作,製作好之後設置狀態變化後可以直接在組件上直接使用;或給每張圖片取好命名規範,在代碼中使用Renderer組件進行循環更換也可以實現幀動畫。
或者使用其他第三方插件也可以,但大同小異。
①將幀動畫所需的所有sprite放在一個數組A中,定義一個時間計數器timer和幀frameIndex,通過與設定的每秒的幀數frameCountPersecond進行計算得出當前播放的幀frame,控制場景中的圖片顯示為sprite[]數組中的圖片即可實現幀動畫的播放
int frameIndex = (int)(timer / (1f / frameCountPersecond));
int frame = frameIndex % sprite.length;
spriteRender.sprite = sprites[frame];
②通過將一組排序好的幀動畫的素材直接整組拖入場景中,unity會自動生成一個animation的幀動畫序列,該對象上的animator組件控制幀動畫的播放
③通過animation自定義角色各個狀態的幀動畫,然後通過animator動畫機來自定義設定各個狀態的切換條件來控制各個狀態的動畫的切換
20、對象包含Box Collider 2D組件,且作為trigger使用時,檢測是否有對象進入的函數是?
OnTriggerEnter2D檢測是否有對象進入
OnTriggerStay2D檢測是否有對象在區域內
OnTriggerExit2D檢測是否有對象離開
答:OnTriggerEnter2D() 例如有個play位移拾取金幣,金幣對象就要加上剛體,Box Collider 2D組件,當play進入金幣時,銷毀積分加屬性等。
voidOnTriggerEnter2D (Collider2D collision)
{
if (collision.tag=="Sqian")
{
Destroy(collision.gameObject);
Score += 10;
UpdateScore();
}
}