Updated on 十一月 24, 2021
Unity 3D坦克大战 学习笔记
炮弹发射位置
可以给坦克Prefab增加一个子empty object,位置是坦克炮筒的位置,方向是炮筒方向,这样在发射炮弹脚本处,可以使用这个object的position、rotation。
炮弹碰撞播放粒子特效并销毁炮弹、销毁特效
通过 粒子动画.transform.parent = null 取消粒子与父控件(炮弹)的绑定关系;
Destroy(粒子动画.gameObject, 粒子动画.main.duration) 使得在播放完粒子动画后销毁粒子动画;
Destroy(this.gameObject) 销毁炮弹;
炮弹爆炸播放声音问题
一开始是将播放audio source放在炮弹object中,但是有问题,炮弹碰撞后销毁,声音也随之销毁了。导致无法播放爆炸声音。
正确的做法是将audio source放在爆炸粒子上,随着爆炸粒子销毁。想想也是,因为声音是在爆炸点发出的,如果是跟随炮弹的话,显然声音的位置是不对的。
获取范围内Collider
Collider[] colliders = Physics.OverlapSphere(transform.position, m_ExplosionRadius, m_TankMask);
其中第一个参数是球中心点,第二个参数是半径,第三个参数是要获取的Collider的Layer。
Lerp与SmoothDamp
Lerp是线性的。
private float t1; t1 += Time.deltaTime; transform.position = Vector3.Lerp(startPos, target, t1);
t的值是在0-1范围内。
![](http://zhuqiaochu.truestudio.tech/wp-content/uploads/2021/11/b6c7078e7f584b45a54b945b187f999b.gif)
Lerp有时候被使用在平滑场景:
transform.position = Vector3.Lerp(transform.position, target, 0.1f);
个人认为这种使用方法是不对的,理论上position越来越接近目标位置,但是永远无法达到。
SmoothDamp是平滑的。
public float m_DampTime = 0.2f; private Vector3 m_MoveVelocity; transform.position = Vector3.SmoothDamp(transform.position, m_DesiredPosition, ref m_MoveVelocity, m_DampTime);
![](http://zhuqiaochu.truestudio.tech/wp-content/uploads/2021/11/9131d3ccba7d41eb8a7af9acbb126159.gif)
https://www.jianshu.com/p/8a5341c6d5a6
TransformPoint和InverseTransformPoint
将自身坐标转换成世界坐标,和 将世界坐标转换成自身坐标
用法:transform.InverseTransformPoint(Vector3)
Camera.aspect
宽÷高
Camera.orthographicSize
The viewport size of the Camera when set to Orthographic. 当Camera选择正交模式时的视窗大小。
也就是说Camera是Orthographic模式时,可以通过设置orthographicSize以实现镜头拉近、拉远的效果。
注意这个size = 视窗高度的一半
![](http://zhuqiaochu.truestudio.tech/wp-content/uploads/2021/11/wx_ss.png)
while循环中yield return null;
private IEnumerator RoundPlaying () { // While there is not one tank left... while (!OneTankLeft()) { // ... return on the next frame. yield return null; } }
yield return null; 的作用是暂缓一帧,和java中的sleep作用是类似的,sleep是指定暂停多少毫秒,yield return null,是暂停一帧,这一帧过后继续while循环,直到判断条件为false,跳出循环,继续。
外层调用为
private IEnumerator GameLoop () { yield return StartCoroutine (RoundStarting ()); yield return StartCoroutine (RoundPlaying()); yield return StartCoroutine (RoundEnding()); if (m_GameWinner != null) { Application.LoadLevel (Application.loadedLevel); } else { StartCoroutine (GameLoop ()); } }
联合起来就是直到round playing结束后,继续后面的代码。
感觉很有用,可以用在游戏关卡通关控制中。
Transform.Translate与Rigidbody.MovePosition
Transform.Translate是单纯的位移,如果碰撞体遇到障碍物,会有一定的问题,例如抖动、穿透等;如果使用Rigidbody.MovePosition则不会有这些问题。
Awake、OnEnable和Start的执行顺序
在同一个脚本中他们的执行顺序是Awake() —> Enable() —> Start()
GameObject的Activity为true,脚本的enable为true时,其先后顺序为:Awake、OnEnable、Start;
GameObject的Activity为true,脚本的enable为false时,只运行Awake;
GameObject的Activity为false时,以上都不调用,OnDisable()被调用;
DustTrail不显示问题
修改粒子属性中”Emiter Velocity”. Change it from Rigidbody to Transform
Slider转圈Progress
正常的Slider的进度是水平的,虽然图片选择成了圆圈,但是如果不设置,还是从左到右。
点击Slider中的Fill,Image Type选择Filled,Fill Method选择Radial 360。
使用InputSystem后,引入UI,导致报错问题
引入UI后,运行报错:
InvalidOperationException: You are trying to read Input using the UnityEngine.Input class, but you have switched active Input handling to Input System package in Player Settings.
解决办法是创建EventSystem,然后再属性中会看到红色叹号,点击下面的Replace with InputSystemUIInputModule。
slider的fill图片变形问题
按照视频里的讲解,给坦克添加蓄力指示箭头。添加完后,发现slider填满后,箭头拉抻变形了,本应是类似Android的9patch,只拉抻一部分。找不到什么原因。
经过不断修改参数尝试,发现修改一些参数可以解决问题,但是不知道所以然。
修改的参数如下:
![](http://zhuqiaochu.truestudio.tech/wp-content/uploads/2021/11/image-2.png)
![](http://zhuqiaochu.truestudio.tech/wp-content/uploads/2021/11/image-3.png)
分别是Sprite和Slider的Fill。