前言
该篇文章主要是总结一些unity常用(涨姿势)的知识,提升自己的同时,也能应付面试。
##回答精辟##
##我只想找个初恋##
Let'Go
1,让一个物体围绕某一点旋转,有几种方法?分别是什么?
旋转函数transform.Rotate()来实现。
transform的RotateAround(vector3 postion,vector3 axis,float angle)函数
2,Mesh,Sphere,Box,Capsule,四种碰撞器。请按照性能开销由小到大进行排序。
性能开销由小到大排序
sphere collider , capsule collider , box collider ,Mesh collider
3,向量的点积,叉积,在游戏中的应用(分别举一个例子说明)
通过点积Vector3.Dot,可以计算两个向量的夹角的。 Vector3.Cross 可以求两个向量的叉积。
Vector3.Dot(transform.forward, target.position)
返回值为正时,目标在自己的前方,反之在自己的后方
判断目标在自己的左右方位可以使用下面的方法:
Vector3.Cross(transform.forward, target.position).y
返回值为正时,目标在自己的右方,反之在自己的左方
通过点积可以计算两个向量的夹角,叉积可以判断目标在自己的方位。向量单位化后可以在游戏中用来计算怪物视野张角;玩家视野张角;NPC视野张角等,完成巡逻索敌等一些功能。
4,请复制下列代码,并在编译器中测试:
[C#]纯文本查看 复制代码
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是一个不折不扣的浮点型,不论它精度有多高,精度损失依然存在!如做大数据的百度,谷歌,财政等,肯定很多时候都要考虑这种问题。
5,如何让粒子效果显示在UI前面?(NGUI或UGUI选其一回答)
1.修改脚本中的RenderQueue值。
2.使用另外一个摄像机,显示特效。
3.修改粒子特效的Shader中的RendererQueue值。
4.结合其他设置,还可以通过3D空间中的Z轴调整
6,当一个细小的高速物体撞向另一个较大的物体时,会出现什么情况?如何避免?
穿透(碰撞检测失败)
射线检测
碰撞体变大
FixedUpdate更新时间修改
代码限制,加大计算量提前计算好下一个位置。
7,Update(),Awake(),Start()的执行顺序是?游戏开始后,分别在何时执行?
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);
}
}
}
12,Unity中游戏暂停和开始怎么实现?
最简单的是设置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不同在于触发之后会一直执行,而且可以获取当前状态。适合用在长时间持续动作,比如行走跑步。
14,两个对象发生碰撞的必要条件是什么?
无论碰撞的两个物体是利用碰撞器,还是利用触发器,都必须带有碰撞器组件Collider(Rigidbody2D),其中一个物体还必须带有Rigidbody(Rigidbody2D)刚体。
人物控制器组件自身包含碰撞,另外一个物体带有Collider就可以发生碰撞。
或者挂上脚本,自行用代码去计算碰撞范围也是可行的,比如AABB。
15,FPS游戏中,哪些东西适合使用对象池技术?
对象池用于需要被反复调用的资源,以减少内存消耗和卡顿等现象,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
19,Unity中如何实现序列帧动画?
准备好序列帧动画的素材,可以是单张也可以是图集(需要设置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();
}
}
写在最后
##代码虐我千百遍,催我快点找初恋##