-
相机能够根据鼠标滑动而移动(类似第三人称游戏镜头控制)
-
发射弧线的小球
-
相机视野有辅助线(瞄准线,类似愤怒的小鸟瞄准线)
-
方块能判断哪一方向被击中
demo版本1.0
demo版本2.0
两个场景资源包,免费下载
网盘链接:
链接:https://pan.baidu.com/s/1P9Uj7i6v-NPlrIB6rE-0Dg
提取码:f8sd
第一个使用的手动添加力和赋予初速度(没用用重力)的方法,不同角度发射小球运动轨迹相同(在碰到物体前),小球碰到物体后运动比较梦幻。代码自己写的。
第二个场景用了重力,不同角度发射小球运动轨迹不同,小球碰到物体后运动会下落。因为项目的临时变化,才改用了重力,由于赶时间,在计算轨迹上用了别人的代码【Unity】预计算刚体运动轨迹_萧然-CSDN博客_unity 轨迹线
部分细节 子弹发射部分(注意,最后把施加力的代码放在了FixedUpdate里面,这点非常重要,后面有简单的讲解)- 由于镜头会移动、要用刚体控制,而且目标位置不是固定的,所以实现子弹弧线运动没有我想的那么简单
(该方法已经弃用)
在Fire类
//向前运动 bulletSon.GetComponent().velocity = bulletSon.transform.forward * speedZ; 在新的子弹类里面跟新子弹自身竖直方向的力
private void Update() { t += Time.deltaTime; deltaForce = 1f / 2 * a * t * t; gameObject.GetComponent().AddForce(gameObject.transform.up * (gameObject.GetComponent ().deltaForce*(-1))); }
(已弃用)
其实AddForce需要一直存在,才能实现现实生活中的力的效果,如果只在函数里面调用一次AddForce,就相当于只附加了一个初速度。
(现在用的此方法)
然后稍微优化了一下结构,把速度放在子弹的类里面
public class BulletParameter : MonoBehaviour { public float deltaForce = 0 ; private float a = 10.5f; private float t = 0; private float speedFront = 9f; private void Start() { //不能放在update里面,会覆盖速度 //向前运动 gameObject.GetComponent().velocity = transform.forward * speedFront; } private void Update() { t += Time.deltaTime; deltaForce = 1f / 2 * a * t * t; //相当于自身的竖直方向 gameObject.GetComponent ().AddForce(gameObject.transform.up * (gameObject.GetComponent ().deltaForce*(-1))); } }
只是当子弹碰撞物体后,就会很鬼畜地乱飞,还挺有意思的。如果以世界坐标应该就不会有这种情况,但是这样的话就需要改变镜头的控制方式,不满足需求。
(最终采用的方法)
如果需要平抛运动可以这样,力放在FixedUpdate里面这点非常非常重要,不然后面根据公式计算的辅助线会和运动轨迹不重合!
using System.Collections; using System.Collections.Generic; using UnityEngine; public class BulletParameter : MonoBehaviour { private float speedFront = 9f;//向前运动的速度 private float forceVertical = -0.3f;//竖直方向的力 //已弃用 //public float deltaForce = 0 ;//力的变化 //private float a = 11f;//力的变化速率 //private float t = 0;//运动时间 private void Start() { //不能放在update里面,会覆盖速度 //向前运动 gameObject.GetComponent().velocity = transform.forward * speedFront; } private void FixedUpdate() { //t += Time.deltaTime; //deltaForce = 1f / 2 * a * t * t; //相当于自身的竖直方向,此为类平抛运动 //gameObject.GetComponent ().AddForce(gameObject.transform.up * (gameObject.GetComponent ().deltaForce*(-1))); //此为平抛运动 gameObject.GetComponent ().AddForce(gameObject.transform.up * forceVertical); } }
- 子弹发射需要开启碰撞连续检测
bulletSon.GetComponent().collisionDetectionMode = CollisionDetectionMode.Continuous;//bulletSon是我自己的子弹类
- 让子弹自身的坐标和当前相机一致,有助于控制不同角度发射子弹和辅助线瞄准的功能
bulletSon.transform.rotation = gameObject.transform.rotation;轨迹弧线部分
- 因为Linerenderer画的线我用着有些地方有些卡手,不方便,画的线是扁的所以我就用预制体代替点,描出运动轨迹。轨迹点通过物理公式计算得到。
- 可能有人会想直接抛出一个物体记录轨迹点,就可以省去计算的过程。实际上,物体抛出后,需要时间运动,这个时间会带来巨大的延迟,当你稍微移动一下视野,等半天才能得到轨迹。所以需要直接计算出来。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class DrawLineObject : MonoBehaviour { public BulletParameter bullet; public GameObject camera;//获得相机 public GameObject pointObject;//充当辅助线点 的预制体 private GameObject[] points;//辅助线的点 private float speedFront;//向前运动的速度 private float forceVertical;//竖直方向力 private float lineTime;//线能触及到子弹运动的时长 private int pointNums;//点的个数 private void Awake() { speedFront = bullet.speedFront; //camera = GameObject.Find("MainCamera"); forceVertical = bullet.forceVertical; lineTime = 0.5f; pointNums = 5; points = new GameObject[pointNums]; for(int i = 0; i < pointNums; i++) { points[i] = Instantiate(pointObject); } } private void Update() { //获得单位时间,用单位时间算点的位移 float interval = lineTime / pointNums; for (int i = 1; i <= pointNums; i++) { Vector3 pointNow = camera.transform.position; //pointNow = camera.transform.position; pointNow += camera.transform.forward * speedFront * interval * i; pointNow += camera.transform.up * forceVertical * 0.5f * Mathf.Pow((interval * i), 2); points[i - 1].transform.position = pointNow; } } }方向判断
- 思路概括:
当发生碰撞时,用子弹的坐标和方块的坐标减,得到新坐标,新坐标xyz中绝对值最大的轴和它的正负即可判断被击中的面
- 我先用了一个枚举保存方向
using System.Collections; using System.Collections.Generic; using UnityEngine; public enum Direction { Up=2, Down=-2, Right=1, Left=-1, Front=3, Back=-3 }
- 判断方向的代码,此处不再赘述。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SideJudge : MonoBehaviour { private void OnCollisionEnter(Collision collision) { if(collision.gameObject.tag == "bullet") { Vector3 Direct = collision.transform.position - this.transform.position;//坐标相减 var dir = CollDirection(Direct);//判断方向 print(gameObject.name + "的" + dir + "边,坐标为:" + Direct + "被击中"); } } Direction CollDirection(Vector3 direct) { int index = 0; float[] array = new float[] { direct.x, direct.y, direct.z }; //根据数值最大轴的正负判断 for (int i = 0; i < 3; i++) { if (Mathf.Abs(direct[i]) > Mathf.Abs(direct[index])) { index = i; } } return (Direction)( (index + 1) * (int)(direct[index] / Mathf.Abs(direct[index]) ) ); } }镜头移动
只需要一个看向点、读取鼠标状态,然后改变位置即可。