Unity腳本基礎
1.Unity3D中的協程(coroutine)和C#線程之間的區別是什么?
多線程程序同時運行多個線程,而在任一指定時刻只有一個協程在運行,并且這個正在運行的協同程序只在必要時才被掛起。除主線程之外的線程無法訪問Unity3D的對象、組件、方法。
Unity3d沒有多線程的概念,不過 unity 也給我們提供了 StartCoroutine(協同程序)和LoadLevelAsync(異步加載關卡)后臺加載場景的方法。 StartCoroutine 為什么叫協同程序呢,所謂協同,就是當你在 StartCoroutine 的函數體里處理一段代碼時,利用 yield 語句等待執行結果,這期間不影響主程序的繼續執行,可以協同工作。而 LoadLevelAsync 則允許你在后臺加載新資源和場景,所以再利用協同,你就可以前臺用 loading 條或動畫提示玩家游戲未卡死,同時后臺協同處理加載的事宜
2.簡述Unity3D支持的作為腳本的語言的名稱
Unity的腳本語言基于 Mono 的.Net 平臺上運行,可以使用.NET 庫,這也為 XML、數據庫、正則表達式等問題提供了很好的解決方案。
Unity里的腳本都會經過編譯,他們的運行速度也很快。這三種語言實際上的功能和運行速度是一樣的,區別主要體現在語言特性上。
JavaScript:和網頁中常用的 JavaScript 不一樣,它編譯后的運行速度很快,語法方面也會有不少區別。
C#、Boo:可以看做是 Python 語言的變種,又糅合了 Ruby 和 C#的特性,它是靜態類型語言
3.Unity3D是否支持寫成多線程程序?如果支持的話需要注意什么?
僅能從主線程中訪問Unity3D的組件,對象和 Unity3D 系統調用
4.支持:如果同時你要處理很多事情或者與Unity的對象互動小可以用 thread,否則使用coroutine。
注意:C#中有 lock 這個關鍵字,以確保只有一個線程可以在特定時間內訪問特定的對象
5.OnEnable、Awake、Start 運行時的發生順序?哪些可能在同一個對象周期中反復的發生?
Awake -》OnEnable-》Start? ? OnEnable在同一周期中可以反復地發生
6.請簡述OnBecameVisible及 OnBecameInvisible 的發生時機,以及這一對回調函數的意義?
當物體是否可見切換之時。可以用于只需要在物體可見時才進行的計算。
7.Unity3D如何獲知場景中需要加載的數據?
Resource.Load
AssetBundle.Load
8.物體發生碰撞時,有幾個階段,分別對應的函數
三個階段,OnCollisionEnter/Stay/Exit函數
9.u3d中,幾種施加力的方式,描述出來
rigidbody.AddForce/AddForceAtPosition,都是 rigidbody 的成員函數
10.物體自旋轉使用的函數叫什么
transform.Rotate
11.物體繞某點旋轉使用函數叫什么
transform.RotateAround
12.u3d提供了一個用于保存讀取數據的類,(playerPrefs),請列出保存讀取整形數據的函數
PlayerPrefs.SetInt與 PlayerPrefs.GetInt
13.unity3d從喚醒到銷毀有一段生命周期,請列出系統自己調用的幾個重要方法。
Awake–>OnEnable –> Start –> Update –> FixedUpdate –> LateUpdate –>OnGUI –> Reset –> OnDisable –> OnDestroy
14.物理更新一般在哪個系統函數里?
FixedUpdate,每固定幀繪制時執行一次,和 update 不同的是 FixedUpdate 是渲染幀執行,如果你的渲染效率低下的時候 FixedUpdate 調用次數就會跟著下降。FixedUpdate 比較適用于物理引擎的計算,因為是跟每幀渲染有關。Update 就比較適合做控制。
15.移動相機動作在哪個函數里,為什么在這個函數里。
LateUpdate,,是在所有 update 結束后才調,比較適合用于命令腳本的執行。官網上例子是攝像機的跟隨,都是在所有 update 操作完才跟進攝像機,不然就有可能出現攝像機已經推進了,但是視角里還未有角色的空幀出現。
16.為什么u3d會出現組件上數據丟失的情況
一般是組件上綁定的物體對象被刪除了
17.什么是協同程序?
在主線程運行時同時開啟另一段邏輯處理,來協助當前程序的執行。換句話說,開啟協程就是開啟一個線程。可以用來控制運動、序列以及對象的行為。
18.反向旋轉動畫的方法是什么?
反轉動畫,講動畫的速度調到-1,碰撞時,被碰撞物體與碰撞物體有collider 組件,碰撞物體有剛體組件,或角色碰撞得包含角色組件 OR 改變 animation.speed
19.用代碼實現第三角色控制器
public class Player : MonoBehaviour?{
????public Transform _cameraTrans;
????private Vector3 _cameraOffset;
????void Awake()?{
????????_cameraOffset = transform.position - _cameraTrans.position;
????}
????void Update()?{
????????_cameraTrans.position = transform.position - _cameraOffset;
????}
}
20.實現吊機吊物體的功能
吊機吊物體需要節點掛接和坐標系轉換
21.獲取、增加、刪除組件的命令分別是什么
獲取:GetComponent
增加:AddComponent
刪除:Destroy
22.Animation.CrossFade命令作用是:C
A. 動畫放大B.動畫轉換 C.動畫的淡入為其他動畫
23.Application.loadLevel命令為:A
A.加載關卡B.異步加載關卡 C.加載動作
24.?調試記錄到控制臺的命令是什么?
Debug.Log();
25.編輯器類存放路徑是什么?
工程目錄下的Assets/Editor文件夾下。
26.使用原生GUI創建一個可以拖動的窗口命令是什么?
GUI.DragWindow();
27.localPosition與 Position 的使用區別?
localPosition:自身位置,相對于父級的變換的位置。 Position:在世界坐標 transform的位置
28.含義Mathf.Round, Mathf.Clamp, Mathf.Lerp
Mathf.Round四舍五入
Mathf.Clamp限制
Mathf.Lerp插值
29.寫一個計時器工具,從整點開始計時,格式為:00:00:00
private float timer = 0f;
private int h = 0;
private int m = 0;
private int s = 0;
private string timeStr = string.Empty;
void Update () {
timer += Time.deltaTime;
????if (timer >= 1f) {s++; ?timer = 0;}
????if (s >= 60) {m++;s = 0;}
if (m >= 60) {h++;m = 0;}
????if (h >= 99) {h = 0;}
}
void OnGUI(){
timeStr = string.Format ("{0:D2}:{1:D2}:{2:D2}", h, m, s);
????GUI.Label (new Rect (10, 10, 100, 200), timeStr);
}
30.寫出Animation的五個方法
AddClip添加剪輯、Blend 混合、Play 播放、Stop 停止、Sample 采樣
31.用鼠標實現在場景中拖動物體,用鼠標滾輪實現縮放(用一個 Cube 即可)。
在場景中添加一個Plan,Camera,Directional Light,Cube。添加兩個腳本scrollerScirpt(掛在Camera),CubeDragScript(掛在Cube上)。
1.鼠標滾輪實現縮放:將攝像機的鏡頭拉近或者拉遠,調整攝像機的視角就可以實現,主要實現代碼如下:
void Update () {
//鼠標滾輪的效果
?????if (Input.GetAxis("Mouse ScrollWheel") < 0) {
??????????if (Camera.main.fieldOfView <= 100)
???????????????Camera.main.fieldOfView += 2;
??????????if (Camera.main.orthographicSize <= 20)
???????????????Camera.main.orthographicSize += 0.5F;
?????}
?????//Zoom in
?????if (Input.GetAxis("Mouse ScrollWheel") > 0) {
??????????if (Camera.main.fieldOfView > 2)
???????????????Camera.main.fieldOfView -= 2;
??????????if (Camera.main.orthographicSize >= 1)
???????????????Camera.main.orthographicSize -= 0.5F;
?????}
}
2.鼠標實現在場景中拖動物體:
解決思路就是將世界坐標轉換成屏幕坐標,然后計算物體與鼠標之間移動量,循環鼠標被按下操作,得到鼠標的當前位置,加上計算好的移動量,將新的坐標賦值給物理就行了。主要是開啟一個協同程序(Corountine)來處理
主要代碼如下:
// Use this for initialization
void Start () {
?????StartCoroutine(OnMouseDown());
}
IEnumerator OnMouseDown()?{
//將物體由世界坐標系轉換為屏幕坐標系
?????Vector3 screenSpace = Camera.main.WorldToScreenPoint(transform.position);
//完成兩個步驟 1.由于鼠標的坐標系是2維,需要轉換成3維的世界坐標系
//2.只有3維坐標情況下才能來計算鼠標位置與物理的距離,offset即是距離
//將鼠標屏幕坐標轉為三維坐標,再算出物體位置與鼠標之間的距離
?????Vector3 offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenSpace.z));
?????while (Input.GetMouseButton(0)) {
//得到現在鼠標的2維坐標系位置
??????????Vector3 curScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenSpace.z);
//將當前鼠標的2維位置轉換成3維位置,再加上鼠標的移動量
??????????Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenSpace) + offset;
//curPosition就是物體應該的移動向量賦給transform的position屬性
??????????transform.position = curPosition;
yield return new WaitForFixedUpdate(); //這個很重要,循環執行
?????}
}
32.NGUI Button怎樣接受用戶點擊并調用函數,具體方法名稱是什么
1、主要是在UICamera腳本中用射線判斷點擊的物體并通過SendMessage調用OnClick() OnPress()等函數,可以說NGUI的按鈕是通過發消息這個方式調用的。具體方法名稱是OnClick()
2、void Awake ()?{
//獲取需要監聽的按鈕對象
???????GameObject button = GameObject.Find("UI Root/Button3");
//設置這個按鈕的監聽,指向本類的ButtonClick方法中。
???????UIEventListener.Get(button).onClick = OnButton3Click;
???}
???private void OnButton3Click(GameObject button)?{
Debug.Log("我是按鈕3被點擊了");
}
33.<憤怒的小鳥>給予初速度以后,怎么讓小鳥受到重力和空氣阻力的影響而繪制拋物線軌跡,說出具體的計算方法.?
Vector3 v代表初速度 v'代表現在的速度, 假設小鳥是沿的 z 軸也就是 transform.forward方向運動的質量為 1,那么 v'=v-new Vector3(0,g*t,f*t),transform.Translate(v')做的就是拋物線運動(g 為重力加速度不要用現實中的需要自己調試,f 為阻力也要自己調試設置,t 為時間)
34.當游戲中需要頻繁創建一個物體時,我們需要怎樣做能夠節省內存?
1、使用預制物體對象 Prefab
2、使用對象池技術,不使用時關閉,使用時打開
35.碰撞檢測需要物體具備什么屬性?
能檢測碰撞發生的方式有兩種,一種是利用碰撞器,另一種則是利用觸發器
【Physics.OverlapSphere相交球檢測碰撞,碰撞檢測需要包圍盒】
36.Vector3.forward與Vector3(0,0,1)是一樣的意思對嗎?
對
37.下哪個函數在游戲進入新場景后會被馬上調用?
MonoBehaviour.OnLevelWasLoaded
38.itween插件的作用是什么,itween 作用于世界坐標還是局部坐標,請列舉出 3 個其常用方法?
iTween是一個動畫庫,作者創建它的目的就是最小的投入實現最大的產出。讓你做開發更輕松,用它可以輕松實現各種動畫,晃動,旋轉,移動,褪色,上色,控制音頻等等“方法:
a、MoveTo 物體移動;
b、ColorTo:隨著時間改變對象的顏色組;
c、LookTo:隨時間旋轉物體讓其臉部朝向所提供的 Vector3 或 Transform 位置;
39.U3D中用于記錄節點空間幾何信息的組件名稱,及其父類名稱
Transform父類是 Component
40.NGUI:把子控件放在父控件里面,如何上下邊距都是10。
給子控件設置上下兩個錨點為10
41.如何使子控件居中,如果使用UGUI怎么實現
設置子控件錨點為中心
42.去掉敏感字的程序(手寫程序)
String s = "你是壞蛋";
s.Replace("壞蛋", "**");
43.unity3D從喚醒到銷毀有一段生命周期,列出系統自己調用的重要方法。
Awake ()
OnEnable ()
Start()
FixedUpdate()
OnTriggerXXX(Collider other)
OnCollisionXXX (Collision collisionInfo)
Update()
LateUpdate ()
OnGUI()
OnDisable ()
OnDestroy ()
44.Unity3d中resources目錄一般用來放些什么,打包的時候會有什么影響?
resource一般用來放置一些需要動態加載的資源,打包程序的時候會將Resource目錄下的全部文件都加密壓縮打進包內,這樣再想使用assetbundle方式打小包的話就不行了
45.空間內一物體繞球面固定點(0、1、2)按照固定速度speed環繞運動。
public float Speed = 1;
void Update ()?{
????transform.RotateAround (new Vector3(0,1,2),Vector3.up,Speed);
}
46.以下關于WWW.LoadFromCacheOrDownload描述正確的是:C
A.可被用于將Text Assets自動緩存到本地磁盤
B.可被用于將Resource自動緩存到本地磁盤
C.可被用于將Assets Bundles自動緩存到本地磁盤
D.可被用于將任意的Unity資源文件自動緩存到本地磁盤
47.以下哪個函數在游戲進入新場景后會被馬上調用?C
A:MonoBehaviour.OnSceneWasLoaded
B:MonoBehaviour.OnSceneEnter
C:MonoBehaviour.OnLevelWasLoaded
D:MonoBehaviour.OnLevelEnter
48.關于MonoBehavior.LateUpdate函數描述錯誤的是:B
A.當MonoBehavior類型應用后,每幀調用一次
B.常被用于處理RigidBody的更新
C.在所有Update函數執行后才能被調用
D.常被用于實現跟隨相機效果,且目標物體的位置已經在Update函數中被更新
49.某個GameObject有一個名為MyScript的腳本,該腳本中有一個名為DoSomething的函數,則如何在該GameObject的另一個腳本中國調用該函數?A
A.GetComponent().DoSomething()
B.GetComponent("MyScript").DoSomething()
C.GetComponent< MyScript >().Call("DoSomething")
D.GetComponent("MyScript"). Call("DoSomething")
50.啟用MipMaps對內存的影響是?A
A.增加約33%的內存
B.減少約33%的內存
C.增加約25%的內存
D.減少約25%的內存
51.以下關于MonoBehaviour.OnGUI()的描述的是:D
A.如果MonoBehaviour沒有被啟用,則OnGUI函數不會被調用
B.用于繪制和處理GUI events
C.每幀可能會被繪制多次,每次對應于一個GUI event
D.每幀被調用一次
52.采用Input.mousePosition來獲取鼠標在屏幕上的位置,以下表述正確的是:B
A.左上角為原點(0, 0),右下角為(Screen.Width, Screen.Height)
B.左下角為原點(0, 0),右上角為(Screen.Height, Screen.Width)
C.左下角為原點(0, 0),右上角為(Screen.Width, Screen.Height)
D.左上角為原點(0, 0),右下角為(Screen.Height, Screen.Height)
53.正確排列出下面Unity腳本自帶的函數執行順序Start,Awake,Update,OnUpdate,OnEnable,FixedUpdate,OnGUI,LateUpdate、OnDisable、OnDestory
Awake-->OnEnable-->Start-->Update-->FixedUpdate-->LateUpdate-->OnGUI-->OnDisable -->OnDestory
54.Unity中銷毀GameObject的方式,簡述Destroy和DestroyImmediate的區別
Destroy銷毀場景中的物體,但是內存中它還是存在的,只有當內存不夠時,機制才會將它銷毀并釋放內存。而DestroyImmediate會立即將對象銷毀,并且將內存釋放。
55.Unity中如何派發事件(消息)
在腳本里的Update函數里調用EventDispatcher.Instance().OnTick();就可以了
56.ScriptObject的作用和使用方式
ScriptObject類型經常使用于存儲一些Unity本身不可以打包的一些object,比如字符串,一些類對象,用這個類型的子類型可以用BuildPipeline打包成assetbundle包共后續使用,非常方便。
57.如何檢測物體是否被其他對象遮擋
使用射線進行檢測
58.寫一個角色控制器,鼠標控制屏幕晃動,鼠標控制開槍。
public class Player : MonoBehaviour?{
????public GameObject _prefabBullet;
????private float _angleSpeed = 120f;
????void Update() {
????????float eularY = Input.GetAxis("Mouse X") * _angleSpeed * Time.deltaTime;
????????transform.Rotate(new Vector3(0,?eularY, 0));
????????if (Input.GetMouseButtonDown(0)) {
????????????Instantiate(_prefabBullet, transform.position, transform.rotation);
????????}
????}
}
59.敵人AI,有各種狀態,實現各種狀態之間的切換。
通過狀態機來實現各種狀態之間的切換
60.
1.寫一個角色控制器,鼠標控制屏幕晃動,鼠標控制開槍。
2.敵人AI,有各種狀態,實現各種狀態之間的切換。
3.敵人會和主角對抗,敵人被打到之后,會閃一次紅色,然后紅色比例提升10%,10次攻擊之后,成紅色。
4.敵人會自動攻擊主角,主角也會有顏色變化。
5.敵人會在范圍內巡邏。
6.UI,左邊顯示8個AI的被攻擊次數,右邊顯示AI的攻擊次數排序。
public class Player : MonoBehaviour {
????public Camera _camera;
????public GameObject _prefabBullet;
????private float _angleSpeed = 120f;
//生命值
????private int _life = 10;
//玩家的狀態
????private bool _state = false;
//是否被打到
????public void IsState() {
????????if (_state && _life > 0) {
????????????_life -= 1;
????????????_state = false;
????????} else {
????????????_state = true;
????????}
????}
????public void RoleRotate() {
????????float eularY = Input.GetAxis("Mouse X") * _angleSpeed * Time.deltaTime;
????}
//風發射子彈
????public void RoleShoot() {
????????if (Input.GetMouseButtonDown(0)) {
????????????Instantiate(_prefabBullet, transform.position, transform.rotation);
????????}
????}
}
public class Enemy : MonoBehaviour {
//敵人被打到狀態
????private bool _state = false;
//玩家與敵人距離
????private float _distance;
//角色
????public GameObject _role;
//生命值
????private int _life = 10;
//敵人被攻擊次數
????private int _timeAccack = 0;
//敵人狀態
????public void EnemyState() {
????????if (_distance >= 10f) {
????????????if (_life >= 1 && _state == true) {
????????????????_life -= 1;
????????????????_timeAccack++;
????????????}
????????????_state = false;
????????}
????????else if (_distance >= 0 && _state == false) {
????????????_state = true;
????????}
????}
//敵人與玩家距離
????public void Distance() {
????????_distance = Vector3.Distance(transform.position, _role.transform.position);
????}
????void OnGUI() {
????????GUI.TextArea(new Rect(20, 50, 80, 30), _timeAccack.ToString());
????????GUI.TextArea(new Rect(20, 90, 80, 30), _timeAccack.ToString());
????????GUI.TextArea(new Rect(20, 130, 80, 30), _timeAccack.ToString());
????}
}
61.3D空間有三個cube當做點,有一條魚的模型,要求在三點之間游動,要求轉向平滑一點,控制魚的運動朝向(用四元數和歐拉角)
使用transform.localRotation = Quaternion.Slerp(Quaternion a,Quaternion b,float c)實現物體平滑轉向