前言
该篇文章主要是总结一些unity常用(涨姿势)的知识,提升自己的同时,也能应付面试。
##回答精辟##
Let'Go
1,如何避免点击UI按钮时穿透,同时触发了相同位置场景模型的点击事件的情况?
答:
方法一 : 打开NGUI——Open——CameraTools,把里面的摄像机的勾都打上 ,然后视你需要遮盖的层来选择即可
方法二 : 代码控制,利用UIcamera.hoveredObject 或者UIcamera.isOverUI 可以获取当前鼠标是否停驻在UI界面上,然后我们在场景的点击事件中只需要在事件判断加上判断
鼠标时否停在UI界面的逻辑值即可。
方法三:通过射线分层处理,显示层分为不同的Layer,用射线进行判断是否点击到UI层。
方法四:可以在最下层加个碰撞框作为屏蔽层(不建议)
2,切换场景时,如何让背景音乐持续播放,而不是重新播放?
答:
这里我们假定第一次播放背景音乐的场景为startScence,我们在startScence创建一个新的gameObject,命名为BgmSound.并添加AudioSource组件以及一个空脚本。
在脚本中我们控制AudioSource的播放,为了切换场景音乐持续播放,我们可以在代码中的Awake中加上DontDestroyOnLoad(this.gameObject)。这样就能保证切换不间断。
但是这样会出一个问题,当其他场景切换到此场景的时候场景会多出一个startScence.为了解决这个问题我们就只能把BgmSound动态加载.我们把BmgSound做成一个Prefab.并加上标签bgm.我们在代码中控制.
01 public GameObject bgmObj = null;
02 void Start () {
03 bgmObj =GameObject.FindGameObjectWithTag( "bgm" );
04
05 if(bgmObj==null) {
06
07 bgmObj= (GameObject)Instantiate(prefab); //这里的prefab就是 BgmSound做成的预制体
08
09 }
10
11 }
3,如何实现游戏存档和读档的功能?
答:
对于小型的数据存储可以采用前两种方式 :
方法一: 利用插件如: easy save
方法二: Unity给我们提供了数据持久化方案PlayerPrefs.里面有三个API.SetInt 、SetFloat 、SetString 我们能通过键值形式存储int、float、string 这三种基本数据类型。
对于大型数据,我们更希望的是得到一个结构化的游戏存档.而非前者这样松散的单个数据.
我们可以采用数据序列化的思路,在游戏中将需要保存的信息分类给出id,然后序列化成字符串输出到Json中.
给出Api: JsonConvert.SerializeObject(object ); 将obj序列化成字符串 JsonConvert.DeserializeObject(string,type); 将字符串根据类型反序列转化为obj.
从游戏数据存储的安全性出发,我们还可以对序列化生成的数据进行加密操作.
4,什么是协同程序?请举一个游戏中应用协程的例子。
答:
协同程序,即在主程序运行时同时开启另一段逻辑处理,来协同当前程序的执行。
在Unity中:我们可以把某个需要协同处理的函数的返回值改为 IEnumerator .然后使用 StartCoroutine 开启协程.参数可以为方法名字符串,也可以是方法加().区别就是,字符串做参数的时候协程函
数只能最多有一个参数。而类似于StartCoroutine(Func(int a,int b))则可以使用多个参数。但是字符串做参数的好处是可以用 StopCoroutine 来定向 停止某个协程。在协程函数中我们可以使用
WaitForSeconds(float) 来延迟 float 秒.达到延时效果.
在Unity 协同程序主要是用来延时,其应用有很多地方,比如: 子弹、特效、敌人死亡等的延迟销毁、怪物的定时刷新效果、技能持续时间效果。
一个简单的协程:
01 using UnityEngine;
02 using System.Collections;
03 using System.Collections.Generic;
04
05 public class test : MonoBehaviour {
06 IEnumerator Start()
07 {
08 yield return new WaitForSeconds(2.0f);
09 Destroy(this.gameObject);
10 }
11
12 }
这段代码可以看出,不仅仅我们定义的函数可以设置为 IEnumerator 还可以把Start、Awake 这类函数设为协程函数.
5,什么是游戏框架?使用框架的好处是什么?
答:
我觉得如果把做游戏比喻成画一幅画来说,框架就是把画里面元素的线描好了。至于怎么去组合、怎么涂色就看你的你自己的想法。
在我的理解中,游戏主框架就是整个游戏各个模块的架构。游戏主框架规定了有哪些模块以及这些模块给出的接口,以及管理游戏的各个模块。
使用框架后,游戏分为各个模块,被对于开发者就可以集中精力去实现各个模块内部的逻辑实现。同样的, 在架构下,保证了每个模块的封装,也实现了模块的重用性。
6,如何在Unity中播放视频?
答:
提要:在Unity 中 视频支持.mov、.mpg、.mpeg、.mp4、.avi和.asf.而Unity对于视频都是以MovieTexture来使用的。如果视频中有声音那么在视频文件下面会相应生成audio文件。所以一个完
整的视频播放是应该画面和音频的同步播放。
方法一:基于GameObject上,这种方式可以让影片以任何方式播放,比如你要实现一个教室,教室讲台上有个投影幕,电影应当在投影幕上播放。这样影片播放就是实打实的在荧幕这个游戏
GameObject上面播放。
实现方法:首先你要在播放的地方加个plane。上面挂一个 Play 脚本。
01 using UnityEngine;
02 using System.Collections;
03
04 public class Play : MonoBehaviour
05 {
06
07 //电影纹理
08 public MovieTexture movTexture;
09 public AudioSource audioSource;
10 void Start()
11 {
12 //设置当前对象的主纹理为电影纹理
13 renderer.material.mainTexture = movTexture;
14 //设置电影纹理播放模式为循环
15 movTexture.loop = true;
16 //如果有声音才播放声音
17 audioSource = GetComponent();
18 }
19 public void OnPlay()
20 {
21 movTexture.Play();
22 // audioSource.Play();
23 }
24 public void OnPause()
25 {1536134
26 movTexture.Pause();
27 // audioSource.Pause();
28 }
29 public void OnStop()
30 {
31 movTexture.Stop();
32 // audioSource.Stop();
33 }
34 }
我们将视频生成的MovieTexture拖放复制到movTexture中,如果有声音,应当给plane添加AudioSource组件并把把生成的音频文件拖放到AudioClip处。脚本中给出了三个函数分别对应的是
视频的播放、暂停、停止。
方法二:基于Unity 的OnGUI实现,这样视频就是以UI元素存在于游戏中。
实现方法:这种方法不需要载体。直接可以将脚本挂在Mamera上。
01 using UnityEngine;
02 using System.Collections;
03
04 public class Play : MonoBehaviour
05 {
06
07 //电影纹理
08 public MovieTexture movTexture;
09 public AudioSource audioSource;
10 void Start()
11 {
12 //设置电影纹理播放模式为循环
13 movTexture.loop = true;
14 //如果有声音才播放声音
15 audioSource = GetComponent();
16 }
17
18 void OnGUI()
19 {
20 //绘制电影纹理
21 GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), movTexture, ScaleMode.StretchToFill);
22 }
23 public void OnPlay()
24 {
25 movTexture.Play();
26 // audioSource.Play();
27 }
28 public void OnPause()
29 {
30 movTexture.Pause();
31 // audioSource.Pause();
32 }
33 public void OnStop()
34 {
35 movTexture.Stop();
36 // audioSource.Stop();
37 }
38
39 }
我们将视频生成的MovieTexture拖放复制到movTexture中,如果有声音,应当给plane添加AudioSource组件并把把生成的音频文件拖放到AudioClip处。脚本中给出了三个函数分别对应的是 视频的播放、暂停、停止。
7,跑酷游戏的无尽关卡是如何生成的?
答:
其实跑酷游戏的场景都是由一段一段不同的路径连接而成。为了保证地图的多样性,游戏每段路径都保证了不同,但是保证多个地路段模型的两端都是能够两两连接。这样的话,其实整个游戏实时存在的只有三个路段:1.Player正在运动的路段、2.Player运动的上一个路段、3.Player下一个即将进入的路段。之所以要保证多个路段是因为保证在跑酷中Cmaera在合理的角度可能会有前一段或者后一段路径的视野,我们要保证给玩家的是地图一直存在的效果而不是临时产生。所以我们应该保留三个路段( 这个数值不唯一,因为我们尽可能让一段路径的长度保证足够长。 )
实现: 一个RoadManage脚本,一个Road脚本。前者处理路径的生成和销毁。后者处理Road和Player的数据关系,触发前者的生成、销毁函数。
RoadManage脚本应当挂在Camera、Light等物体上, 每个路径Prefab都是绑定Road脚本。这个脚本能够实时获得Player的位置和自身位置关系。如果当Player刚刚进入RoadA.那么RoadA就通知RoadManage生成一个路径。并销毁自身。大题实现过程就是这样.下面给出样例代码:[源自:siki的逃离地球]
01 using UnityEngine;
02 using System.Collections;
03
04 public class Road: MonoBehaviour
05 {
06 private Transform player;
07 void Awake()
08 {
09 player = GameObject.FindGameObjectWithTag("Player").transform;
10 }
11
12 void Update()
13 {
14 if (player.position.z > transform.position.z + 100)
15 RoadManage._instance.GenerateRoad();
16 Destroy(this.gameObject);
17 }
18 }
[C#] 纯文本查看 复制代码
?
01 using UnityEngine;
02 using System.Collections;
03
04 public class RoadManage : MonoBehaviour
05 {
06 public Road road1;
07 public Road road2; //这里保留了两个路径
08 public int roadCount = 2; //生成的第几个路径用于确定位置
09
10 public GameObject[] roads; //供随机生成的不同路径Prefabs;
11
12 public static RoadManage _instance;
13 void Awake()
14 {
15 _instance = this;
16 }
17
18 public void GenerateRoad()
19 {
20 roadCount++;
21 int type = Random.Range(0, roads.Length);
22 GameObject newRoad = Instantiate(roads[type], new Vector3(0, 0, roadCount * 3000), Quaternion.identity) as GameObject;
23 road1 = road2;
24 road2 = newRoad.GetComponent();
25 }
26 }
PS: 在地图生成和销毁中如果用对象池优化。
8,如何增强ARPG游戏的打击感?
答:
这个不是太了解,我觉得打击感应该就是打击过程中的给玩家反馈的拟真度。真实性越强的打击效果给玩家的打击感越强。那么这个问题其实就是问的如何增强游戏打击的拟真度。
我觉得要增加拟真度可以通过特效、声音、动画等几个方面。
1.特效。不仅仅是游戏中的技能特效。例如武士2中的出血特效、连击特效等等。好的特效不仅仅会给玩家视觉上的享受,还可以让玩家更容易融入游戏场景中。
2.声音。在合适的时机播放正确的音乐可能玩家不会感觉到什么,但是如果在合适的时机没有播放或者播放的不适当的音乐,玩家就会产生强烈的违和感。就假如说对打过程中,如果你的拳头都已经碰到敌人的身体。可以打击音效还没有播放。然而当敌人都飞出去了。音效才播放出来。无疑玩家会感觉十分的不舒服。所以说,选好音效、控制好播放时机对增加游戏的打击感是必不可少的。
3.动画。这里的动画不是简简单单的动画,更应该说是结合游戏过程中物理作用下的模型的反馈。比如说。玩家横向一拳打向敌人,敌人不应该是飞起来。好的动画是应该结合实时的物理条件下的动作反馈。给人以真实的效果呈现。
4.还有一些元素可以增加打击感,例如手柄上的震动或者必杀技的慢放等等。
9,游戏慢镜头回放功能的实现思路?如足球游戏中的精彩镜头回放。
答:
这个效果我没有实现过,但我我觉得可以通过这两种方法实现:
1.对于足球、篮球游戏这种精彩回放往往是进球的那段时间,那么回放核心物体就是球。我们可以使用一个Camera去跟随球。让Camera实时将渲染画面用图片形式保存到文件中(保存的时候也可以清除之前无用的画面 )。如果逻辑上判定为精彩镜头。就可以将保存的图片用动画的方式播放出来。
2.如果是魔兽争霸、LOL这种游戏回放,是可以对游戏的整个场景实时回放的。这样的话就不能用Camera去实现了。但是我们知道一个游戏最关键的就是用户输入和游戏自身的随机数种子。所以我们只需要记录随机数种子和操作序列。然后模拟一遍就可以完全真实的回放整个游戏的真实状态。
10,LOD技术是什么?优缺点是?
答:
LOD( Level of detail )技术是作为Unity优化的一大常用技术。
我们都知道一个模型越是精细,顶点就会越多。渲染的时候就会耗时。所以我们在游戏优化的时候我们除了尽量减少DrawCall也会尽量使得在不影响游戏画面的情况下减少模型的顶点。
生活中我们都会遇到过这样的例子: "诶,你看这东西像吗?" “一般般吧,不过拿远了看还真分辨不出来。”。对,当一个物体离我们眼睛过远的时候我们是用过肉眼很难分辨其精细程度的。那么在游戏中我们知道一个物体不在Camera镜头之内或者说是离Camera很远的时候,无论它是否精细,我们通过肉眼是很难观察到的。这样的话,其实就算模型不是那么精细。也不太会影响游戏画面。所以.LOD技术就是在根据摄像机距离对象的远近,选择使用不同精度的模型。它的好处是可以在适当的时候大量减少需要绘制的顶点数目。这样就达到了优化的作用。
优点就是:合理的使用LOD可以大大减少游戏渲染时间。在保证游戏画面依然精细的条件下让支持游戏的最低配置要求大大减少。
缺点是:当然游戏需要占用更多内存。而且如果在LOD算法没有把握好距离的时候,会让玩家看到模型顶点切换的突变。反而效果不好。
1,LOD是Levels of Detail的简称,译为多细节层次。LOD技术指根据物体模型的节点在显示环境中所处的位置和重要度,决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算。
2,LOD的优点可以根据距离动态地选折渲染不同细节的模型
3,LOD缺点增加项目的包的大小,并且内存会增大,属于内存换效果
在Unity中也可以使用LOD技术,Unity提供了LODgroup这个组件。开发者可以将不同的层次细节的物体模型分别添加到LOD:0~LOD:7中。其中,LOD:0是视点距离最近具体观看下进行显示的模型。一般添加层次细节最丰富的模型,后面依次添加与原始模型外观相同但层次细节逐次降低的模型,最后的“Culled”表示该模型在场景中消失.一般这是指物体非常远或者不在Camera视野内的情况
结束语
##如有错误,欢迎指正##