Unity开发中导弹路径散射的原理与实现

news2024/12/23 17:11:11

Unity开发中导弹路径散射的原理与实现

  • 前言
  • 逻辑原理
  • 代码实现
    • 导弹自身脚本
    • 外部控制脚本
  • 应用效果
  • 结语

前言

前面我们学习了导弹的追踪的效果,但是在动画或游戏中,我们经常可以看到导弹发射后的弹道是不规则的,扭扭曲曲的飞行,然后击中目标。
这期我们就讲一下不规则路径飞行的逻辑,在游戏中是如何实现的。

请添加图片描述

逻辑原理

首先迎面走来的是初级的散射效果原理图,在发射点和目标点之间有一个散射经过点,重点来了:**利用三维空间中球形公式,给定球心,随机返回球面上一点。**然后让导弹经过随机点再击打目标,就会形成随机散射的效果。
在这里插入图片描述
多点也是一样的道理,把路径点经过换算之后再赋值导弹路径点,然后形成不规则散射的效果。
在这里插入图片描述
这里可以发现,导弹的路径是折线效果,按标准应该是曲线效果。两者的区别就在于导弹在两点之间的过渡函数,折线是平滑过渡,曲线是贝塞尔曲线过渡,选的过渡函数不同实现的效果也不一样。由于贝塞尔曲线过渡较为复杂,这里就用平滑过渡演示原理

代码实现

导弹自身脚本

这里将散射的范围用变量表示,实现可控的效果,想大范围就大范围、想小范围就小范围。将脚本挂载到导弹的预制体上之后给相应的变量赋值,例如:散射半径、爆炸特效、子弹移动速度,其他变量通过外部脚本赋值。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SpherePoint : MonoBehaviour
{
    [Header("散射半径")]
    public float radius;
    
    public GameObject FX;//爆炸特效
    public Transform endPoint;   // 目标点  
    public List<Transform> wayPoints; // 中间点列表  
    public float speed = 10f;         // 子弹移动速度  

    public int currentWaypointIndex = 0; // 当前处理的中间点索引  
    public Vector3 currentTargetPosition; // 当前目标位置  

    // Start is called before the first frame update
    void Start()
    {
        if (wayPoints.Count > 0)
        {
            currentTargetPosition = GetRandomPointOnSphere(wayPoints[0].position, radius);
        }
        else
        {
            currentTargetPosition = endPoint.position;
        }


    }

    // Update is called once per frame
    void Update()
    {
    	BulletMovement(transform);
    }

    /// <summary>
    /// 随机获取中间点周围的散射经过点
    /// </summary>
    /// <param name="center">中间点坐标</param>
    /// <param name="r">散射半径</param>
    /// <returns></returns>
    public static Vector3 GetRandomPointOnSphere(Vector3 center, float r)
    {
        // 生成随机的经度和纬度  
        float u = UnityEngine.Random.value * 2 * Mathf.PI; // 经度 [0, 2*PI]  
        float v = UnityEngine.Random.value * Mathf.PI; // 纬度 [0, PI]  

        // 将球坐标转换为笛卡尔坐标  
        float x = center.x + r * Mathf.Sin(v) * Mathf.Cos(u);
        float y = center.y + r * Mathf.Sin(v) * Mathf.Sin(u);
        float z = center.z + r * Mathf.Cos(v);

		//返回指定球心的球面上随机一点
        return new Vector3(x, y, z);
    }

    private void BulletMovement(Transform bulletTran)
    {
        // 子弹朝向当前目标位置  
        bulletTran.LookAt(currentTargetPosition);

        bulletTran.position += bulletTran.forward * speed * Time.deltaTime;      //向前移动

        // 检查子弹是否到达当前目标位置  
        if (Vector3.Distance(bulletTran.position, currentTargetPosition) < 0.1f)
        {
            // 如果当前点不是最后一个中间点,则更新下一个目标位置为下一个中间点  
            if (currentWaypointIndex < wayPoints.Count)
            {
                currentWaypointIndex++;
                if (currentWaypointIndex < wayPoints.Count)
                {
                    currentTargetPosition = GetRandomPointOnSphere(wayPoints[currentWaypointIndex].position, radius);
                }
                else
                {
                    currentTargetPosition = endPoint.position; // 最后一个中间点后,目标位置是终点  
                }
            }
            // 如果已经到达终点,可以选择销毁子弹或其他操作  
            else if (currentTargetPosition == endPoint.position)
            {
                GameObject tempFX = Instantiate(FX, bulletTran.position, bulletTran.rotation);  //生成一个爆炸特效 并给予位置和旋转信息
                Destroy(gameObject);//销毁自己
                Destroy(tempFX, 0.3f);//销毁爆炸效果
                currentWaypointIndex = 0;//重置路径索引
            }
        }
    }

}

在这里插入图片描述

外部控制脚本

将导弹的击打目标和散射路径点通过脚本告诉导弹。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InstantiateBullet : MonoBehaviour
{
    public GameObject bullet;//导弹预制体
    public Vector3 startPoint; // 导弹出生发射点  
    public Quaternion missileRotation;//导弹出生时方向
    public Transform endPoint;   // 目标点  
    public List<Transform> wayPoints; // 中间点列表  
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
    	//鼠标点击左键发射导弹
        if (Input.GetMouseButtonDown(0))
        {
            GameObject bu = Instantiate(bullet, startPoint, missileRotation);
            bu.GetComponent<SpherePoint>().endPoint = endPoint;
            bu.GetComponent<SpherePoint>().wayPoints = wayPoints;
        }
    }
}

外部脚本我挂载到了Main Camera相机上。

在这里插入图片描述

应用效果

先看个正面的:

请添加图片描述

再来个侧面的:

请添加图片描述

好了,结束。

结语

学会后要多尝试,变成自己的东西,为己所用,赶快自己尝试下吧。有什么问题可以评论区或私信留言,下期见,拜拜。

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1666029.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode39.组合总和

文章目录 题目描述解题思路重复子集剪枝 代码 题目 参考题解 题目描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返…

Python | Leetcode Python题解之第78题子集

题目&#xff1a; 题解&#xff1a; class Solution:def subsets(self, nums: List[int]) -> List[List[int]]:self.res []self.backtrack([], 0, nums)return self.resdef backtrack(self, sol, index, nums):self.res.append(sol)for i in range(index, len(nums)):self…

leetcode-矩阵最长递增路径-102

题目要求 思路 1.通过双循环去把每一个结点作为起始点进行统计&#xff0c;将返回的路径长度存放在res中&#xff0c;取最大的res的长度。 2.递归中需要的几个值&#xff0c;x和y当前结点的坐标&#xff0c;pre用于存储上一个结点的元素值&#xff0c;因为要求是路径上的元素是…

Redis简单使用

认识Redis redis&#xff1a;字典型数据库&#xff0c;存储的是键值对&#xff0c;是NoSql数据库 关系型数据库和NoSql之间的区别&#xff1a; 结构化&#xff1a;NoSql非结构化数据库&#xff0c;松散结构&#xff08;键值对key-value&#xff08;可以任意类型&#xff09;&…

科技查新中化工领域查新点如何确立与提炼?案例讲解!

我国化工科技查新工作始于1985年&#xff0c;至今经历了30多年的发展。化工类课题包含化工、炼油、 冶金、能源、轻工、石化、环境、医药、环保和军工等&#xff0c; 具有物质种类繁多、制备工艺复杂等特点。因此&#xff0c;本文结合化工查新项目实例&#xff0c;总结提高化工…

scrapy的入门

今天我们先学习一下scrapy的入门,Scrapy是一个快速的高层次的网页爬取和网页抓取框架&#xff0c;用于爬取网站并从页面中提取结构化的数据。 1. scrapy的概念和流程 1.1 scrapy的概念 我们先来了解一下scrapy的概念,什么是scrapy: Scrapy是一个Python编写的开源网络爬虫框架…

【userfaultfd+条件竞争劫持modprobe_path】TSGCTF 2021 -- lkgit

前言 入门题&#xff0c;单纯就是完成每日一道 kernel pwn 的 kpi &#x1f600; 题目分析 内核版本&#xff1a;v5.10.25&#xff0c;可以使用 userfaultfd&#xff0c;不存在 cg 隔离开启了 smap/smep/kaslr/kpti 保护开启了 SLAB_HADNERN/RANDOM 保护 题目给了源码&…

HarmonyOS NEXT星河版之模拟图片选择器(下)---使用Swiper实现图片滑动预览

文章目录 一、目标二、开撸2.1 改造图片预览Dialog2.2 改造主页面2.3 主页面完整代码 三、小结 一、目标 在前面的介绍中&#xff0c;查看选中的图片都是单张预览&#xff0c;接下来要改造成多张可滑动预览&#xff0c;如下&#xff1a; 二、开撸 2.1 改造图片预览Dialog …

【c++】set、map用法详解

set、map用法详解 1. 关联式容器2. 键值对2.1 &#xff1a;pair2.2&#xff1a;make_pair 3. 树形结构的关联式容器3.1&#xff1a;set构造函数find()erase()insert()count()lower_bound()upper_bound() 3.2&#xff1a;multiset3.3&#xff1a;map构造函数insert()operator[] …

如何在bud里弄3d模型?---模大狮模型网

随着数字化设计的不断发展&#xff0c;越来越多的设计软件提供了对3D模型的支持&#xff0c;为设计师们带来了更广阔的创作空间。Bud作为一款功能强大的设计工具&#xff0c;也提供了添加和编辑3D模型的功能&#xff0c;让用户能够更加灵活地进行设计创作。本文将为您详细介绍如…

最新网页版USB转串口芯片CH340中文规格书手册(20240511)

前言 南京沁恒的产品已经很成熟了&#xff0c;完全可替代国外USB转串口产品&#xff0c;不必迷信FT232&#xff0c;CP2102之类了。 另外&#xff0c;急着买芯片&#xff0c;直接跑过去的&#xff0c;看过几次妹子了:) CH340手册&#xff0c;基于网页3.3版本&#xff0c;规格书…

ARM单片机实现流水灯(GD32)

根据上图可知使用的引脚分别是PA8,PE6,PF6流水灯功能的实现要分别初始化这几个引脚 流水灯实现 编写流水灯代码 LED.C #include "gd32f30x.h" // Device header #include "Delay.h" // 初始化LED灯 void LED_Init(void){// 使能RCU时钟…

正点原子FreeRTOS学习笔记——列表与列表项

目录 一、什么是列表和列表项 1、概念 2、FreeRTOS代码 &#xff08;1&#xff09;列表 &#xff08;2&#xff09;列表项 &#xff08;3&#xff09;迷你列表项 二、列表与列表项初始化 1、列表初始化 2、列表项初始化 三、列表插入与删除列表项 1、原理解释 2、…

2024.1IDEA 到2026年

链接&#xff1a;https://pan.baidu.com/s/1hjJEV5A5k1Z9JbPyBXywSw?pwd9g4i 提取码&#xff1a;9g4i解压之后,按照 操作说明.txt 操作; IntelliJ IDEA 2024.1 (Ultimate Edition) Build #IU-241.14494.240, built on March 28, 2024 Licensed to gurgles tumbles You have…

如何给扫描好的3d模型贴图?---模大狮模型网

在数字化设计领域&#xff0c;3D模型的贴图是提升模型逼真度和视觉效果的重要步骤之一。尤其是对于扫描好的3D模型&#xff0c;通过添加适当的贴图&#xff0c;不仅可以增强模型的细节和真实感&#xff0c;还可以为设计带来更加生动的视觉体验。本文将为您详细介绍如何给扫描好…

探索全画面塑料焊接透光率检测仪的科技魅力

在精密工业和科研领域中&#xff0c;对材料的光学性能有着严格的要求。全画面塑料焊接透光率检测仪是一种先进的设备&#xff0c;它能够精确测量塑料焊接接头的透光率&#xff0c;确保焊接质量符合高标准。本文将详细介绍这一设备的特点、工作原理以及它在实际应用中的重要性。…

【Vue基础】Vue在组件数据传递详解

Vue核心基础-CSDN博客 先回顾Vue特性&#xff1a; Vue.js 是一个用于构建用户界面的渐进式框架&#xff0c;具有许多强大的特性。以下是一些主要的 Vue 特性&#xff1a; 响应式数据&#xff1a;Vue 使用双向绑定来实现数据的响应式更新。当数据发生变化时&#xff0c;视图会自…

LLM一些适合小白的入门项目和视频

AIX 大模型专区学习&#xff08;史上最丰富&#x1f973;&#xff09; https://github.com/stay-leave/enhance_llm 图谱大哥五一写得。 【对于卷积神经网络&#xff0c;硕士博士不需要搞明白原理&#xff0c;只要会应用是这样吗&#xff1f;-pytorch/深度学习/神经网络】 htt…

draw.io 网页版二次开发(3):打包和部署(war包)

目录 一 说明 二 环境配置 1. 下载并安装 Apache Ant 2. 下载并安装JDK和JRE 3. 下载tomcat 4. Ant、JDK和JRE 环境变量的配置 三 draw.io打包 四 部署 五 最后 一 说明 应公司项目要求&#xff0c;需要对draw.io进行二次开发&#xff0c;并将html界面通过iframe 嵌…

超详细的胎教级Stable Diffusion使用教程(四)

这套课程分为五节课&#xff0c;会系统性的介绍sd的全部功能和实操案例&#xff0c;让你打下坚实牢靠的基础 一、为什么要学Stable Diffusion&#xff0c;它究竟有多强大&#xff1f; 二、三分钟教你装好Stable Diffusion 三、小白快速上手Stable Diffusion 四、Stable dif…