unity demo免费下载:第三人称镜头移动+瞄准线+发射弧线球打击方块(方块可以识别受击方向)demo

Unity: 第三人称视野移动+瞄准线+发射弧线球打击方块(方块可以识别受击方向)demo

功能描述:

  • 相机能够根据鼠标滑动而移动(类似第三人称游戏镜头控制)

  • 发射弧线的小球

  • 相机视野有辅助线(瞄准线,类似愤怒的小鸟瞄准线)

  • 方块能判断哪一方向被击中

演示

请添加图片描述
demo版本1.0
unity demo免费下载:第三人称镜头移动+瞄准线+发射弧线球打击方块(方块可以识别受击方向)demo_第1张图片
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画的线我用着有些地方有些卡手,不方便,画的线是扁的所以我就用预制体代替点,描出运动轨迹。轨迹点通过物理公式计算得到。
    unity demo免费下载:第三人称镜头移动+瞄准线+发射弧线球打击方块(方块可以识别受击方向)demo_第2张图片
  • 可能有人会想直接抛出一个物体记录轨迹点,就可以省去计算的过程。实际上,物体抛出后,需要时间运动,这个时间会带来巨大的延迟,当你稍微移动一下视野,等半天才能得到轨迹。所以需要直接计算出来。
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]) ) );
    }
}

镜头移动

只需要一个看向点、读取鼠标状态,然后改变位置即可。

你可能感兴趣的:(分享,unity,游戏引擎,经验分享)