Unity面试题——Unity脚本基础

简介: Unity面试题——Unity脚本基础

107. Unity3D 中的协程(coroutine)和 C#线程之间的区别是什么?

多线程程序同时运行多个线程 ,而在任一指定时刻只有一个协程在运行,并且这个正在运行的协同程 序只在必要时才被挂起。除主线程之外的线程无法访问 Unity3D 的对象、组件、方法。 Unity3d 没有多线程的概念,不过 unity 也给我们提供了 StartCoroutine(协同程序)和 LoadLevelAsync(异步加载关卡)后台加载场景的方法。 StartCoroutine 为什么叫协同程序呢,所谓协同,就是当你在 StartCoroutine 的函数体里处理一段代码时,利用 yield 语句等待执行结果,这期间不影响主程序的继 续执行,可以协同工作。而 LoadLevelAsync 则允许你在后台加载新资源和场景,所以再利用协同,你 就可以前台用 loading 条或动画提示玩家游戏未卡死,同时后台协同处理加载的事宜

108. 简述 Unity3D 支持的作为脚本的语言的名称

Unity 的脚本语言基于 Mono 的.Net 平台上运行,可以使用.NET 库,这也为 XML、数据库、正则表达式 等问题提供了很好的解决方案。 Unity 里的脚本都会经过编译,他们的运行速度也很快。这三种语言实际上的功能和运行速度是一样的, 区别主要体现在语言特性上。 JavaScript:和网页中常用的 JavaScript 不一样,它编译后的运行速度很快,语法方面也会有不少区别。 C# Boo:可以看做是 Python 语言的变种,又糅合了 Ruby 和 C#的特性,它是静态类型语言

109. Unity3D 是否支持写成多线程程序?如果支持的话需要注意什么?

仅能从主线程中访问 Unity3D 的组件,对象和 Unity3D 系统调用

110. 支持:如果同时你要处理很多事情或者与 Unity 的对象互动小可以用 thread,否则使用 coroutine。

注意:C#中有 lock 这个关键字,以确保只有一个线程可以在特定时间内访问特定的对象

111. OnEnable、Awake、Start 运行时的发生顺序?哪些可能在同一个对象周 期中反复的发生?

Awake -》OnEnable-》Start OnEnable 在同一周期中可以反复地发生

112. 、请简述 OnBecameVisible 及 OnBecameInvisible 的发生时机,以及这 一对回调函数的意义?

当物体是否可见切换之时。可以用于只需要在物体可见时才进行的计算。

113. Unity3D 如何获知场景中需要加载的数据?

Resource.Load

AssetBundle.Load

114. 物体发生碰撞时,有几个阶段,分别对应的函数

三个阶段,OnCollisionEnter/ /Exit 函数

115. u3d 中,几种施加力的方式,描述出来

rigidbody.AddForce/AddForceAtPosition,都是 rigidbody 的成员函数

116. 物体自旋转使用的函数叫什么

transform.Rotate

117. 物体绕某点旋转使用函数叫什么

transform.RotateAround

118. u3d 提供了一个用于保存读取数据的类,(playerPrefs),请列出保存读取 整形数据的函数

PlayerPrefs.SetInt 与 PlayerPrefs.GetInt

119. unity3d 从唤醒到销毁有一段生命周期,请列出系统自己调用的几个重要 方法。

Awake –>OnEnable –> Start –> Update –> FixedUpdate –> LateUpdate –>OnGUI –> Reset –>

OnDisable –> OnDestroy

120. 物理更新一般在哪个系统函数里?

FixedUpdate,每固定帧绘制时执行一次,和 update 不同的是 FixedUpdate 是渲染帧执行,如果你的渲 染效率低下的时候 FixedUpdate 调用次数就会跟着下降。FixedUpdate 比较适用于物理引擎的计算,因 为是跟每帧渲染有关。Update 就比较适合做控制。

121. 移动相机动作在哪个函数里,为什么在这个函数里。

LateUpdate,,是在所有 update 结束后才调,比较适合用于命令脚本的执行。官网上例子是摄像机的跟 随,都是在所有 update 操作完才跟进摄像机,不然就有可能出现摄像机已经推进了,但是视角里还未 有角色的空帧出现。

122. 为什么 u3d 会出现组件上数据丢失的情况

一般是组件上绑定的物体对象被删除了

123. 什么是协同程序?

在主线程运行时同时开启另一段逻辑处理,来协助当前程序的执行。换句话说,开启协程就是开启一 个线程。可以用来控制运动、序列以及对象的行为。

124. 反向旋转动画的方法是什么?

反转动画,讲动画的速度调到-1,碰撞时,被碰撞物体与碰撞物体有 collider 组件,碰撞物体有刚体组 件,或角色碰撞得包含角色组件 OR 改变 animation.speed

125. 用代码实现第三角色控制器

public class Player : MonoBehaviour {
public Transform _cameraTrans;
private Vector3 _cameraOffset;
void Awake() {
_cameraOffset = transform.position - _cameraTrans.position;
}
void Update() {
_cameraTrans.position = transform.position - _cameraOffset;
}
}

126. 实现吊机吊物体的功能

吊机吊物体需要节点挂接和坐标系转换

127. 获取、增加、删除组件的命令分别是什么

获取:GetComponent

增加:AddComponent

删除:Destroy

128. Animation.CrossFade 命令作用是:C

A. 动画放大 B.动画转换 C.动画的淡入为其他动画

129. Application.loadLevel 命令为:A

A. 加载关卡 B.异步加载关卡 C.加载动作

130. 调试记录到控制台的命令是什么?

Debug.Log();

131. 编辑器类存放路径是什么?

工程目录下的 Assets/Editor 文件夹下。

132. 使用原生 GUI 创建一个可以拖动的窗口命令是什么?

GUI.DragWindow();

133. localPosition 与 Position 的使用区别?

localPosition:自身位置,相对于父级的变换的位置。 Position:在世界坐标 transform 的位置

134. 含义 Mathf.Round, Mathf.Clamp, Mathf.Lerp

Mathf.Round 四舍五入

Mathf.Clamp 限制

Mathf.Lerp 插值

135. 写一个计时器工具,从整点开始计时,格式为: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);
}

136. 写出 Animation 的五个方法

AddClip 添加剪辑、Blend 混合、Play 播放、Stop 停止、Sample 采样

137. 用鼠标实现在场景中拖动物体,用鼠标滚轮实现缩放(用一个 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(); //这个很重要,循环执行
}
}

138. 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 被点击了");
}

139. <愤怒的小鸟>给予初速度以后,怎么让小鸟受到重力和空气阻力的影响而绘 制抛物线轨迹,说出具体的计算方法.

Vector3 v 代表初速度 v'代表现在的速度, 假设小鸟是沿的 z 轴也就是 transform.forward 方向运动 的质量为 1,那么 v'=v-new Vector3(0,gt,ft),transform.Translate(v')做的就是抛物线运动(g 为重力加 速度不要用现实中的需要自己调试,f 为阻力也要自己调试设置,t 为时间)

140. 当游戏中需要频繁创建一个物体时,我们需要怎样做能够节省内存?

1、使用预制物体对象 Prefab

2、使用对象池技术,不使用时关闭,使用时打开

141. 碰撞检测需要物体具备什么属性?

能检测碰撞发生的方式有两种,一种是利用碰撞器,另一种则是利用触发器 【Physics.OverlapSphere 相交球检测碰撞,碰撞检测需要包围盒】

142. Vector3.forward 与 Vector3(0,0,1)是一样的意思对吗?

143. 下哪个函数在游戏进入新场景后会被马上调用?

MonoBehaviour.OnLevelWasLoaded

144. itween 插件的作用是什么,itween 作用于世界坐标还是局部坐标,请列 举出 3 个其常用方法?

iTween 是一个动画库,作者创建它的目的就是最小的投入实现最大的产出。让你做开发更轻松,用它 可以轻松实现各种动画,晃动,旋转,移动,褪色,上色,控制音频等等“方法:

a、MoveTo 物体移动;

b、ColorTo:随着时间改变对象的颜色组;

c、LookTo:随时间旋转物体让其脸部朝向所提供的 Vector3 或 Transform 位置;

145. U3D 中用于记录节点空间几何信息的组件名称,及其父类名称

Transform 父类是 Component

146. NGUI:把子控件放在父控件里面,如何上下边距都是 10。

给子控件设置上下两个锚点为 10

147. 如何使子控件居中,如果使用 UGUI 怎么实现

设置子控件锚点为中心

148. 去掉敏感字的程序(手写程序)

String s = "你是坏蛋";

s.Replace("坏蛋", "**");

149. unity3D 从唤醒到销毁有一段生命周期,列出系统自己调用的重要方法。

Awake ()
OnEnable ()
Start()
FixedUpdate()
OnTriggerXXX(Collider other)OnCollisionXXX (Collision collisionInfo)
Update()
LateUpdate ()
OnGUI()
OnDisable ()
OnDestroy ()

150. Unity3d 中 resources 目录一般用来放些什么,打包的时候会有什么影响?

resource 一般用来放置一些需要动态加载的资源,打包程序的时候会将 Resource 目录下的全部文件都 加密压缩打进包内,这样再想使用 assetbundle 方式打小包的话就不行了

151. 空间内一物体绕球面固定点(0、1、2)按照固定速度 speed 环绕运动。

public float Speed = 1;
void Update () {
transform.RotateAround (new Vector3(0,1,2),Vector3.up,Speed);
}

152. 以下关于 WWW.LoadFromCacheOrDownload 描述正确的是: C

A.可被用于将 Text Assets 自动缓存到本地磁盘

B.可被用于将 Resource 自动缓存到本地磁盘

C.可被用于将 Assets Bundles 自动缓存到本地磁盘

D.可被用于将任意的 Unity 资源文件自动缓存到本地磁盘

153. 以下哪个函数在游戏进入新场景后会被马上调用? C

A:MonoBehaviour.OnSceneWasLoaded

B:MonoBehaviour.OnSceneEnter

C:MonoBehaviour.OnLevelWasLoaded

D:MonoBehaviour.OnLevelEnter

154. 关于 MonoBehavior.LateUpdate 函数描述错误的是: B

A.当 MonoBehavior 类型应用后,每帧调用一次

B.常被用于处理 RigidBody 的更新

C.在所有 Update 函数执行后才能被调用

D.常被用于实现跟随相机效果,且目标物体的位置已经在 Update 函数中被更新155. 某个 GameObject 有一个名为 MyScript 的脚本,该脚本中有一个名为

DoSomething 的函数,则如何在该 GameObject 的另一个脚本中国调用该

函数? A

A.GetComponent().DoSomething()

B.GetComponent

C.GetComponent< MyScript >().Call("DoSomething")

D.GetComponent

156. 启用 MipMaps 对内存的影响是? A

A.增加约 33%的内存

B.减少约 33%的内存

C.增加约 25%的内存

D.减少约 25%的内存

157. 以下关于 MonoBehaviour.OnGUI()的描述的是: D

A.如果 MonoBehaviour 没有被启用,则 OnGUI 函数不会被调用

B.用于绘制和处理 GUI events

C.每帧可能会被绘制多次,每次对应于一个 GUI event

D.每帧被调用一次

158. 采用 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)

159. 正确排列出下面 Unity 脚本自带的函数执行顺序 Start,Awake,Update, OnUpdate,OnEnable,FixedUpdate,OnGUI,LateUpdate、OnDisable、 OnDestory

Awake-->OnEnable-->Start-->Update-->FixedUpdate-->LateUpdate-->OnGUI-->OnDisable -->OnDestory

160. Unity 中销毁 GameObject 的方式,简述 Destroy 和 DestroyImmediate 的区别

Destroy 销毁场景中的物体,但是内存中它还是存在的,只有当内存不够时,机制才会将它销毁并释放 内存。而 DestroyImmediate 会立即将对象销毁,并且将内存释放。

161. Unity 中如何派发事件(消息)

在脚本里的 Update 函数里调用 EventDispatcher.Instance().OnTick();就可以了

162. ScriptObject 的作用和使用方式

ScriptObject 类型经常使用于存储一些 Unity 本身不可以打包的一些 object,比如字符串,一些类对象, 用这个类型的子类型可以用 BuildPipeline 打包成 assetbundle 包共后续使用,非常方便。

163. 如何检测物体是否被其他对象遮挡

使用射线进行检测

164. 写一个角色控制器,鼠标控制屏幕晃动,鼠标控制开枪。

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);
}
}
}

165. 敌人 AI,有各种状态,实现各种状态之间的切换。

通过状态机来实现各种状态之间的切换

166. 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());
}
}

167. 3D 空间有三个 cube 当做点,有一条鱼的模型,要求在三点之间游动,要 求转向平滑一点,控制鱼的运动朝向(用四元数和欧拉角)

使用 transform.localRotation = Quaternion.Slerp(Quaternion a,Quaternion b,float c)实现物体平滑转向

目录
相关文章
|
6月前
|
存储 人工智能 Java
Unity优化——脚本优化策略4
Unity优化——脚本优化策略4
109 0
|
2月前
|
设计模式 存储 人工智能
深度解析Unity游戏开发:从零构建可扩展与可维护的游戏架构,让你的游戏项目在模块化设计、脚本对象运用及状态模式处理中焕发新生,实现高效迭代与团队协作的完美平衡之路
【9月更文挑战第1天】游戏开发中的架构设计是项目成功的关键。良好的架构能提升开发效率并确保项目的长期可维护性和可扩展性。在使用Unity引擎时,合理的架构尤为重要。本文探讨了如何在Unity中实现可扩展且易维护的游戏架构,包括模块化设计、使用脚本对象管理数据、应用设计模式(如状态模式)及采用MVC/MVVM架构模式。通过这些方法,可以显著提高开发效率和游戏质量。例如,模块化设计将游戏拆分为独立模块。
166 3
|
3月前
|
图形学 C# 开发者
全面掌握Unity游戏开发核心技术:C#脚本编程从入门到精通——详解生命周期方法、事件处理与面向对象设计,助你打造高效稳定的互动娱乐体验
【8月更文挑战第31天】Unity 是一款强大的游戏开发平台,支持多种编程语言,其中 C# 最为常用。本文介绍 C# 在 Unity 中的应用,涵盖脚本生命周期、常用函数、事件处理及面向对象编程等核心概念。通过具体示例,展示如何编写有效的 C# 脚本,包括 Start、Update 和 LateUpdate 等生命周期方法,以及碰撞检测和类继承等高级技巧,帮助开发者掌握 Unity 脚本编程基础,提升游戏开发效率。
73 0
|
5月前
|
人工智能 图形学
【unity小技巧】使用动画状态机脚本实现一个简单3d敌人AI功能
【unity小技巧】使用动画状态机脚本实现一个简单3d敌人AI功能
45 0
|
5月前
|
人工智能 定位技术 图形学
【Unity小技巧】一个脚本实现控制3D远程/近战敌人AI
【Unity小技巧】一个脚本实现控制3D远程/近战敌人AI
48 0
|
5月前
|
自然语言处理 图形学
【unity实战】一个通用的FPS枪支不同武器射击控制脚本
【unity实战】一个通用的FPS枪支不同武器射击控制脚本
69 0
|
5月前
|
程序员 图形学 Android开发
Unity脚本生命周期
Unity脚本生命周期
|
6月前
|
存储 人工智能 缓存
Unity优化——脚本优化策略3
Unity优化——脚本优化策略3
|
6月前
|
存储 缓存 Java
Unity优化——脚本优化策略2
Unity优化——脚本优化策略2
|
6月前
|
存储 XML 缓存
Unity优化——脚本优化策略1
Unity优化——脚本优化策略1