前言
該篇文章主要是總結(jié)一些unity常用(漲姿勢(shì))的知識(shí),提升自己的同時(shí),也能應(yīng)付面試。
##回答精辟##
##我只想找個(gè)初戀##
Let'Go
1偏形,讓一個(gè)物體圍繞某一點(diǎn)旋轉(zhuǎn),有幾種方法觉鼻?分別是什么俊扭?
旋轉(zhuǎn)函數(shù)transform.Rotate()來實(shí)現(xiàn)。
transform的RotateAround(vector3 postion,vector3 axis,float angle)函數(shù)
2坠陈,Mesh萨惑,Sphere,Box仇矾,Capsule庸蔼,四種碰撞器。請(qǐng)按照性能開銷由小到大進(jìn)行排序贮匕。
性能開銷由小到大排序
sphere collider , capsule collider , box collider ,Mesh collider
3姐仅,向量的點(diǎn)積,叉積,在游戲中的應(yīng)用(分別舉一個(gè)例子說明)
通過點(diǎn)積Vector3.Dot掏膏,可以計(jì)算兩個(gè)向量的夾角的劳翰。 Vector3.Cross 可以求兩個(gè)向量的叉積。
Vector3.Dot(transform.forward, target.position)
返回值為正時(shí),目標(biāo)在自己的前方,反之在自己的后方
判斷目標(biāo)在自己的左右方位可以使用下面的方法:
Vector3.Cross(transform.forward, target.position).y
返回值為正時(shí),目標(biāo)在自己的右方,反之在自己的左方
通過點(diǎn)積可以計(jì)算兩個(gè)向量的夾角馒疹,叉積可以判斷目標(biāo)在自己的方位磕道。向量單位化后可以在游戲中用來計(jì)算怪物視野張角;玩家視野張角行冰;NPC視野張角等,完成巡邏索敵等一些功能伶丐。
4悼做,請(qǐng)復(fù)制下列代碼,并在編譯器中測(cè)試:
[C#]純文本查看 復(fù)制代碼
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”的輸出結(jié)果為多少哗魂?為什么肛走?如果解決?
首先录别,變量“d”的輸出結(jié)果為119朽色。
先解釋為什么:在程序中精確計(jì)算中使用浮點(diǎn)數(shù)是非常危險(xiǎn)的,盡管C#在浮點(diǎn)數(shù)運(yùn)算時(shí)采取了很多措施使得浮點(diǎn)數(shù)運(yùn)算的結(jié)果看起來是非常正常的组题。但實(shí)際上如果不清楚浮點(diǎn)數(shù)的特性而貿(mào)然使用的話(浮點(diǎn)數(shù)由于是計(jì)算機(jī)內(nèi)部求補(bǔ)運(yùn)算而進(jìn)行的葫男,因此可能存在誤差。)崔列,將造成非常嚴(yán)重的隱患梢褐。而且在精度損失的時(shí)候,不會(huì)報(bào)告任何的錯(cuò)誤赵讯,也不會(huì)有任何的異常產(chǎn)生~
小數(shù)多位后容易出現(xiàn)誤差盈咳,使用double會(huì)看得更多有效數(shù)字,但依然會(huì)有誤差边翼,最后真正強(qiáng)轉(zhuǎn)為int的實(shí)際上是一個(gè)199.9……無限接近于200的數(shù)鱼响,這個(gè)時(shí)候,應(yīng)該改變計(jì)算公式组底≌苫或者把最后的intd = (int)c;改為更高精度的decimal。即可正常斤寇。
最后,所有的浮點(diǎn)型變量都存在精度損失的問題桶癣!而decimal是一個(gè)不折不扣的浮點(diǎn)型,不論它精度有多高娘锁,精度損失依然存在牙寞!如做大數(shù)據(jù)的百度,谷歌,財(cái)政等间雀,肯定很多時(shí)候都要考慮這種問題悔详。
5,如何讓粒子效果顯示在UI前面惹挟?(NGUI或UGUI選其一回答)
1.修改腳本中的RenderQueue值茄螃。
2.使用另外一個(gè)攝像機(jī),顯示特效连锯。
3.修改粒子特效的Shader中的RendererQueue值归苍。
4.結(jié)合其他設(shè)置,還可以通過3D空間中的Z軸調(diào)整
6运怖,當(dāng)一個(gè)細(xì)小的高速物體撞向另一個(gè)較大的物體時(shí)拼弃,會(huì)出現(xiàn)什么情況?如何避免摇展?
穿透(碰撞檢測(cè)失斘茄酢)
射線檢測(cè)
碰撞體變大
FixedUpdate更新時(shí)間修改
代碼限制,加大計(jì)算量提前計(jì)算好下一個(gè)位置咏连。
7盯孙,Update(),Awake(),Start()的執(zhí)行順序是?游戲開始后祟滴,分別在何時(shí)執(zhí)行振惰?
Awake——>Start——>Update
腳本自帶函數(shù)執(zhí)行順序如下:將下面腳本掛在任意物體運(yùn)行即可得到
Awake ->OnEable-> Start ->FixedUpdate-> Update -> LateUpdate ->OnGUI ->Reset -> OnDisable->OnDestroy
8,數(shù)列 1,1,2,3,5,8,13... 第 n 位數(shù)是多少 ? 用 C# 遞歸算法實(shí)現(xiàn)
public int function(intn)
{
if(n == 1 || n == 2)
return 1;
else
return function(n - 1) + function(n - 2);
}
9,當(dāng)游戲中需要頻繁創(chuàng)建一個(gè)物體對(duì)象時(shí)垄懂,我們需要怎么做來節(jié)省內(nèi)存?
使用pool對(duì)象池报账。
使用AssetBundle也可以降低一定內(nèi)存。
10埠偿,Unity動(dòng)態(tài)加載資源有幾種方法透罢,分別是什么?
通過Resources模塊冠蒋,調(diào)用它的load函數(shù):可以直接load并返回某個(gè)類型的Object羽圃,前提是要把這個(gè)資源放在Resource命名的文件夾下,Unity不關(guān)有沒有場(chǎng)景引用抖剿,都會(huì)將其全部打入到安裝包中朽寞。
通過bundle的形式:即將資源打成 asset bundle 放在服務(wù)器或本地磁盤,然后使用WWW模塊get 下來斩郎,然后從這個(gè)bundle中l(wèi)oad某個(gè)object脑融。
通過AssetDatabase.loadasset :這種方式只在editor范圍內(nèi)有效,游戲運(yùn)行時(shí)沒有這個(gè)函數(shù)缩宜,它通常是在開發(fā)中調(diào)試用的
11肘迎,如何實(shí)現(xiàn)磁鐵效果甥温?比如酷跑游戲中,獲得磁鐵道具后妓布,自動(dòng)吸附附近金幣的效果姻蚓。
獲得磁鐵效果后,主要流程可以分為3步:
首先判斷金幣是否進(jìn)入磁鐵有效范圍(圓半徑匣沼,距離狰挡,矩形,collider觸發(fā)器等方式都可以)
接著可以使用差值運(yùn)算方法释涛,Lerp方法或ITween等插件或者類似方法對(duì)金幣做一個(gè)緩動(dòng)效果吸附的動(dòng)畫,
最后判斷動(dòng)畫到達(dá)目標(biāo)點(diǎn)后(碰撞器加叁,觸發(fā)器,計(jì)時(shí)等)進(jìn)行銷毀加分等處理即可唇撬。
①在玩家身上相同的坐標(biāo)位置創(chuàng)建一個(gè)空的gameobject作為自物體殉农,添加圓形或者球形碰撞器(根據(jù)實(shí)際要求2D或者3D)來選擇,勾選istrigger作為觸發(fā)器局荚,觸發(fā)器的范圍即為磁鐵吸附范圍,添加剛體愈污,取消勾選useGravity耀态,gameobject.setActive(false);
②當(dāng)玩家獲得磁鐵道具后,控制該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);
}
}
}
12暂雹,Unity中游戲暫停和開始怎么實(shí)現(xiàn)首装?
最簡(jiǎn)單的是設(shè)置Time.timeScale = 0,即可讓游戲暫停,也可以使用Time.timeScale來做游戲的 1倍2倍整體加速杭跪,但要記住無論Time.timeScale等于多少Update和LateUpdate都會(huì)去執(zhí)行仙逻,所以這兩個(gè)方法里面需要自己用代碼控制。而且如果游戲暫停以后想在暫停界面上繼續(xù)播放一些不受Time.timeScale影響的動(dòng)畫或者粒子特效之類的涧尿,那么我們就需要用到Time.realtimeSinceStartup去單獨(dú)恢復(fù)他們系奉,還有聲音部分也需要單獨(dú)恢復(fù)timeScale。
最大的影響是姑廉,在timeScale=0時(shí)無法實(shí)現(xiàn)暫停菜單的動(dòng)畫以及各種漂亮的點(diǎn)擊效果缺亮。
如果只想暫停某部分,或者為了更多需求和可擴(kuò)展性桥言,還是需要自己寫個(gè)相關(guān)的Manager來手動(dòng)管理游戲的暫停和開始萌踱。
13,Animator Controller中參數(shù)類型bool和trigger的區(qū)別是什么号阿?分別在何種情況下使用并鸵?
animator的trigger變量只能賦值,是一種觸發(fā)變量扔涧,觸發(fā)之后會(huì)自動(dòng)關(guān)閉掉园担,沒辦法獲取當(dāng)前狀態(tài)。
比如xxxx.animator.settrigger("Attack");在執(zhí)行這一句時(shí)才是true ,但是執(zhí)行后馬上自動(dòng)的變?yōu)閒alse粉铐。適合用在單次動(dòng)作或者連續(xù)不同動(dòng)作使用疼约,比如三國(guó)無雙系列的攻擊和蓄力攻擊。
bool跟trigger不同在于觸發(fā)之后會(huì)一直執(zhí)行蝙泼,而且可以獲取當(dāng)前狀態(tài)程剥。適合用在長(zhǎng)時(shí)間持續(xù)動(dòng)作,比如行走跑步。
14汤踏,兩個(gè)對(duì)象發(fā)生碰撞的必要條件是什么织鲸?
無論碰撞的兩個(gè)物體是利用碰撞器,還是利用觸發(fā)器溪胶,都必須帶有碰撞器組件Collider(Rigidbody2D)搂擦,其中一個(gè)物體還必須帶有Rigidbody(Rigidbody2D)剛體。
人物控制器組件自身包含碰撞哗脖,另外一個(gè)物體帶有Collider就可以發(fā)生碰撞瀑踢。
或者掛上腳本,自行用代碼去計(jì)算碰撞范圍也是可行的,比如AABB才避。
15橱夭,F(xiàn)PS游戲中,哪些東西適合使用對(duì)象池技術(shù)桑逝?
對(duì)象池用于需要被反復(fù)調(diào)用的資源,以減少內(nèi)存消耗和卡頓等現(xiàn)象棘劣,F(xiàn)PS游戲中包括要常被大量復(fù)制的對(duì)象:子彈,敵人楞遏,濺血特效茬暇,彈坑以及任何重復(fù)出現(xiàn)的對(duì)象。
16寡喝,Lightmapping是什么糙俗?為什么要使用?
光照貼圖预鬓。使用Lightmapping預(yù)先模擬燈光帶來的效果臼节,會(huì)帶來性能上的大大提升,手機(jī)上更明顯。當(dāng)然會(huì)損失畫面效果珊皿,具體還是看項(xiàng)目需求网缝。最簡(jiǎn)單的直接在3dmas或maya里面烘培完貼圖頂點(diǎn)色也行。
與Lightmapping相關(guān)的LightProbes也偶爾會(huì)使用蟋定,
用烘焙出來的假光在動(dòng)態(tài)的物體或角色沒有受光會(huì)很突兀粉臊,顯得很戳。想要?jiǎng)討B(tài)物體也有這樣的效果就需要用到LightProbes驶兜。
17扼仲,在塔防游戲中远寸,如何讓塔指向進(jìn)入攻擊范圍的敵人并射擊?請(qǐng)簡(jiǎn)述程序流程屠凶。
先判斷NPC是否進(jìn)入攻擊范圍(圓半徑驰后,距離,矩形矗愧,collider觸發(fā)器等)灶芝。
根據(jù)塔的種類進(jìn)行不同處理:
單目標(biāo)攻擊:記錄第一個(gè)進(jìn)入范圍的NPC,使用Lookat或者差值運(yùn)算讓塔面向目標(biāo),然后利用ITween播放子彈動(dòng)畫,目標(biāo)為NPC唉韭,進(jìn)行鎖定射擊夜涕。
范圍群體目標(biāo)攻擊:記錄所有在塔范圍的NPC,存入List集合属愤,每次攻擊遍歷集合并重復(fù)調(diào)用前面提到的單目標(biāo)攻擊的方法女器。
指向性飛行道具:用碰撞器或觸發(fā)器,直接對(duì)NPC進(jìn)行碰撞檢測(cè)即可住诸。
18驾胆,Unity中,控制3D人物模型位移方式有幾種?Animator組件的Apply Root Motion的作用是贱呐?
1丧诺、this.m_transform.position= pos;在Update函數(shù)中調(diào)用
2、transform.Translate(Vector3direction)
3吼句、CharacterController.Move(),CharacterController.simplemove()
4事格、Rigidbody.MovePosition();Rigidbody.velocity= Vector3.forward * MoveSpeed; Rigidbody.AddForce();
5惕艳、Vector3.MoveToward 當(dāng)前的地點(diǎn)移向目標(biāo)
如果勾選了Animator組件中的ApplyRoot Motion選項(xiàng)
角色的Transform將不能通過腳本來直接賦值,而是通過動(dòng)畫的運(yùn)動(dòng)的來改變的
如果我們不勾選驹愚,我們就可以用腳本改變角色的Tranform
19远搪,Unity中如何實(shí)現(xiàn)序列幀動(dòng)畫?
準(zhǔn)備好序列幀動(dòng)畫的素材逢捺,可以是單張也可以是圖集(需要設(shè)置Multiple模式在Sprite Editor切割)谁鳍。
然后使用Animation進(jìn)行動(dòng)畫制作,制作好之后設(shè)置狀態(tài)變化后可以直接在組件上直接使用;或給每張圖片取好命名規(guī)范劫瞳,在代碼中使用Renderer組件進(jìn)行循環(huán)更換也可以實(shí)現(xiàn)幀動(dòng)畫倘潜。
或者使用其他第三方插件也可以,但大同小異志于。
①將幀動(dòng)畫所需的所有sprite放在一個(gè)數(shù)組A中涮因,定義一個(gè)時(shí)間計(jì)數(shù)器timer和幀frameIndex,通過與設(shè)定的每秒的幀數(shù)frameCountPersecond進(jìn)行計(jì)算得出當(dāng)前播放的幀frame伺绽,控制場(chǎng)景中的圖片顯示為sprite[]數(shù)組中的圖片即可實(shí)現(xiàn)幀動(dòng)畫的播放
int frameIndex = (int)(timer / (1f / frameCountPersecond));
int frame = frameIndex % sprite.length;
spriteRender.sprite = sprites[frame];
②通過將一組排序好的幀動(dòng)畫的素材直接整組拖入場(chǎng)景中养泡,unity會(huì)自動(dòng)生成一個(gè)animation的幀動(dòng)畫序列嗜湃,該對(duì)象上的animator組件控制幀動(dòng)畫的播放
③通過animation自定義角色各個(gè)狀態(tài)的幀動(dòng)畫,然后通過animator動(dòng)畫機(jī)來自定義設(shè)定各個(gè)狀態(tài)的切換條件來控制各個(gè)狀態(tài)的動(dòng)畫的切換
20澜掩,對(duì)象包含Box Collider 2D組件购披,且作為trigger使用時(shí),檢測(cè)是否有對(duì)象進(jìn)入的函數(shù)是肩榕?
OnTriggerEnter2D檢測(cè)是否有對(duì)象進(jìn)入
OnTriggerStay2D檢測(cè)是否有對(duì)象在區(qū)域內(nèi)
OnTriggerExit2D檢測(cè)是否有對(duì)象離開
答:OnTriggerEnter2D() 例如有個(gè)play位移拾取金幣刚陡,金幣對(duì)象就要加上剛體,Box Collider 2D組件点把,當(dāng)play進(jìn)入金幣時(shí)橘荠,銷毀積分加屬性等。
voidOnTriggerEnter2D (Collider2D collision)
{
if (collision.tag=="Sqian")
{
Destroy(collision.gameObject);
Score += 10;
UpdateScore();
}
}
寫在最后
##代碼虐我千百遍郎逃,催我快點(diǎn)找初戀##