Unity3d面试4

来源:互联网 发布:火狐不支持java 编辑:程序博客网 时间:2024/05/18 01:57
http://www.taidous.com/bbs/thread-36457-1-2.html
泰斗社区 Unity问答第1期
Unity问答第2期

1,向量的点积,叉积,在游戏中的应用(分别举一个例子说明)
  • 判断目标在自己的前后方位可以使用下面的方法:
[C#] 纯文本查看 复制代码
?
 
Vector3.Dot(transform.forward, target.position)
返回值为正时,目标在自己的前方,反之在自己的后方
  • 判断目标在机子的左右方位可以使用下面的方法:
[C#] 纯文本查看 复制代码
?
 
Vector3.Cross(transform.forward, target.position).y
返回值为正时,目标在自己的右方,反之在自己的左方
  • a.normalized  和  b.normalized  表示的是两个向量的单位向量, 因为在公式里,有向量和模的除法,得出来的结果就是单位向量,所以我们这里和后面都直接用单位向量来计算,省去不少麻烦。
  • Mathf.Rad2Deg 表示的是 单位弧度的度数。详情请见作者文章:  Unity3D之Mathf.Rad2Deg和Mathf.Deg2Rad
  • 通过叉积计算度数是通过公式 |c|=|a||b|sin<a,b> 来逆向求值。|c| 其实就是叉积的模,换句话说,也代表着 Vector3.Distance (Vector3.zero, Vector3.Cross (a.normalized, b.normalized))的值。


  • 通过点积可以计算两个向量的夹角,叉积可以判断目标在自己的方位。向量单位化后可以在游戏中用来计算怪物视野张角;玩家视野张角;NPC视野张角等,完成巡逻索敌等一些功能。

2,输出: 600,0.2,120,119;
该方式对于浮点数会做无条件舍去,失去精确度。  
如果希望获取float的整数部分可以 d = Math.Floor(c);
  • Math.Round:四舍六入五
  • Math.Ceiling:只要有小数都加1  Math.Ceil(1.3f)
  • Math.Floor:总是舍去小数

4,如何让粒子效果显示在UI前面?(NGUI或UGUI选其一回答)
  • 如果是NGUI修改粒子的renderQueue,修改尽量大就在所有UI上面,如果希望在2个UI之间就需要看看NGUI源码,http://m.blog.csdn.net/blog/yxriyin/44037673
  • 如果是UGUI一种是可以使用相机把处理粒子,一种是设置sortingOrder http://www.xuanyusong.com/archives/3435
1.修改脚本中的RenderQueue值。
2.使用另外一个摄像机,显示特效。
3.修改粒子特效的Shader中的RendererQueue值。
4.结合其他设置,还可以通过3D空间中的Z轴调整

5,当一个细小的高速物体撞向另一个较大的物体时,会出现什么情况?如何避免?
会发生穿透(碰撞检测失败)
解决方法:
  • 增大细小物体的碰撞体
  • 使用射线检测
  • 可以physics time减小,不建议这样做
  • 确保rigidbody不超过一定的速度,这个也不实用
7,Update(),Awake(),Start()的执行顺序是?游戏开始后,分别在何时执行?
Awake()-> Start()-> Update();
脚本自带函数执行顺序如下:将下面脚本挂在任意物体运行即可得到
Awake ->OnEable-> Start -> FixedUpdate-> Update  -> LateUpdate ->OnGUI ->Reset -> OnDisable ->OnDestroy

  • Awake:用于在游戏开始之前初始化变量或游戏状态。在脚本整个生命周期内它仅被调用一次.Awake在所有对象被初始化之后调用,所以你可以安全的与其他对象对话或用诸如GameObject.FindWithTag()这样的函数搜索它们。每个游戏物体上的Awake以随机的顺序被调用。因此,你应该用Awake来设置脚本间的引用,并用Start来传递信息Awake总是在Start之前被调用。它不能用来执行协同程序
  • Start:仅在Update函数第一次被调用前调用Start在behaviour的生命周期中只被调用一次它和Awake的不同是Start只在脚本实例被启用时调用。你可以按需调整延迟初始化代码。Awake总是在Start之前执行。这允许你协调初始化顺序。在所有脚本实例中,Start函数总是在Awake函数之后调用。
  • Update:正常帧更新,用于更新逻辑。每一帧都执行,处理Rigidbody时,需要用FixedUpdate代替Update。例如:给刚体加一个作用力时,你必须应用作用力在FixedUpdate里的固定帧,而不是Update中的帧。(两者帧长不同)FixedUpdate,每固定帧绘制时执行一次,和update不同的是FixedUpdate是渲染帧执行如果你的渲染效率低下的时候FixedUpdate调用次数就会跟着下降。FixedUpdate比较适用于物理引擎的计算,因为是跟每帧渲染有关。Update就比较适合做控制。

  • 碰撞体变大, FixedUpdate频率修改。代码限制,加大计算量提前计算好下一个位置。
8,当游戏中需要频繁创建一个物体对象时,我们需要怎么做来节省内存?
  • 使用pool对象池。
  • 使用AssetBundle也可以降低一定内存。
使用对象池,预先创建好要使用的物体,使用的时候从池里面取,用完之后放回去。
切换场景之后可以进行回收。理想状态下自己管理所有的对象,CG机制只起辅助作用。

9,Unity动态加载资源有几种方法,分别是什么?
  • 通过Resources模块,调用它的load函数:可以直接load并返回某个类型的Object,前提是要把这个资源放在Resource命名的文件夹下,Unity不关有没有场景引用,都会将其全部打入到安装包中。
  • 通过bundle的形式:即将资源打成 asset bundle 放在服务器或本地磁盘,然后使用WWW模块get 下来,然后从这个bundle中load某个object。
  • 通过AssetDatabase.loadasset :这种方式只在editor范围内有效,游戏运行时没有这个函数,它通常是在开发中调试用的

1,如何实现磁铁效果?比如酷跑游戏中,获得磁铁道具后,自动吸附附近金币的效果
答:1,可以使用碰撞器实现,在获得磁铁效果后加大player的碰撞器(如果不需要player有跳跃动作可以实现),金币监听player的状态获得               磁铁效果金币加大 碰撞器。金币可以有自己的layer
    2,使用触发器,方法同上不会出现跳跃后没法落地的效果,不过方法能实现确不是很实用。
    3,使用FindGameObjectsWithTag查找金币获得金币的数组,然后通过Vector3.Distance()的方法对距离进行判断在进行销毁。因为获得状态时肯定是有很多
        金币所以要获取的是金币数组。
     4,Unity里有个物理,Physics.OverlapSphere()也可以实现要注意相机的层和深度。
2,Unity中游戏暂停和开始怎么实现?
答:1,Time.timeScale = 0 可以暂停游戏,但这是作用于整个游戏的设置,不单单是当前场景,记得在需要的时候重置回Time.timeScale = 1。
        时间流动速度变为0,但是translate位移动画不能停住,用了第一人称的胶囊体的话镜头依旧能转动,所以所有Transform的移动都应该写在update并跟Time.deltaTime
        相乘的这样才能使速度稳定,这些位置变动便会停掉的。

    2,补充有关于暂停的相关有个帖子还是不错的 http://www.xuanyusong.com/archives/2956
3,Animator Controller中参数类型bool和trigger的区别是什么?分别在何种情况下使用?
答:1,从数据结构看都属于bool类型,trigger在Animator组件中被触发就会自动变为false状态,它只是个触发事件,一旦触发就自动变换数值。
    2,然而bool用于多状态切换比较常用。
5,FPS游戏中,哪些东西适合使用对象池技术?
答:对象池就存放需要被反复调用资源的一个空间,比如游戏中要常被大量复制的对象,子弹,敌人,技能特效以及任何频繁重复出现的对象。
方正需要不断实例化的东西就用对象池就没错了
6,Lightmapping是什么?为什么要使用?
答:烘培贴图,实时灯光计算十分耗时,随着光源越多会倍增计算耗时。使用Lightmap模拟灯光带来的效果,便不用去计算灯光,会带来性能
    上的大大提升。当然你不用灯光效果也是没问题的,具体还是看项目需求。最简单的直接在3dmas或maya里面烘培完贴图顶点色也行。
7,在塔防游戏中,如何让塔指向进入攻击范围的敌人并射击?请简述程序流程。
答:1,利用画格子的方法把地图分割成等比小格子,
       敌人只负责发送事件,其他的一概不管。每到一个新的格子就发出一个事件比如:GridChange,这个事件通过冒泡到他的上层容器。
       上层容器侦听GridChange事件。一旦侦听到后就通知附近攻击范围内的炮塔。
       炮塔可以设定为几种策略:如果已经有目标则不理会新目标或者永远攻击新目标。
       炮塔攻击目标直到目标走出范围或者死亡。
    2,也可以使用触发器,当敌人进入触发器后播放攻击动画,攻击朝向是被攻击AI的坐标方向。直到出范围或死亡换下一目标。
    3,也可以动画事件当动画执行到某一帧的情况下添加事件判断敌人是否在攻击范围内,如果在敌人响应被攻击的方法。
8,Unity中,控制3D人物模型位移方式有几种?Animator组件的Apply Root Motion的作用是?
答:1,常用的位移方式有4种组件,如下方法,除了一下方法还有角色控制器移动。
        transform.translate()向某方向移动物体多少距离【默认local坐标系】
        transform.Position()在世界空间坐标transform的位置
        RigidBody.Velocity刚体的速度向量
        RigidBody.AddForce添加一个力到刚体。作为结果刚体将开始移动。
        RigidBody.MovePosition移动刚体到position
        NavMeshAgent组件的SetDestination函数,设置自动Path目标点
        CharacterController组件的Move函数,每次都绝对运动
        Vector3.MoveToward 当前的地点移向目标
    2,如果我们勾选了Animator组件中的Apply Root Motion选项,角色的Transform将不能通过脚本来直接赋值,而是通过动画的运动的来改变的
       如果我们不勾选我们就可以用脚本改变角色的Tranform

9,Unity中如何实现序列帧动画?
答:1,Window→Animation组件。切割好的帧图片直接拖入Unity,Hierarchy中自动生成帧动画
    2,也可以通过程序来实现,例如以每帧一个图形文件来控制。
using UnityEngineusing System.Collections;public class test : MonoBehaviour{float timeElapsed = 0;int curFrame = 0;float fps = 10;Texture2D[] ani;void Update(){timeElapsed += Time.deltaTime;if(timeElapsed >= 1.0 / fps){timeElapsed  = 0;curFrame++;}guiTexture.texture = ani[curFrame];}}

10,对象包含Box Collider 2D组件,且作为trigger使用时,检测是否有对象进入的函数是?
答:OnTriggerEnter2D()例如有个play位移拾取金币,金币对象就要加上刚体,
Box Collider 2D组件,当play进入金币时,销毁积分加属性等。
// using UnityEngine// using System.Collections;// public class test : MonoBehaviour// {// float timeElapsed = 0;// int curFrame = 0;// float fps = 10;// Texture2D[] ani;// void Update()// {// timeElapsed += Time.deltaTime;// if(timeElapsed >= 1.0 / fps)// {// timeElapsed  = 0;// curFrame++;// }// guiTexture.texture = ani[curFrame];// }// }using UnityEngine;using System.Collections;public class test : MonoBehaviour{void Start(){}void Update(){}void OnTriggerEnter2D(collider2D collision){if(collision.tag == "Sqian"){Destroy)(collision.gameObject);Score += 10;UpdateScore();}}}











0 0
原创粉丝点击