• Unity3D


    相关网址汇总


    1.Unity官网(外网):https://unity.com

    2.Unity官网(内网):https://unity.cn

    3.Unity学习:
    https://learn.unity.com
    https://learn.unity.com/projects

    4.Unity官方商店:https://assetstore.unity.com

    基本操作以及模块简介

    视角操作以及组件

    组件设置
    1.导航器Gizmo:表示世界坐标的方向
    2.栅格Grid:表示XZ坐标平面
    3.天空盒Skybox:表示游戏世界的背景

    3D视图
    1.旋转视图:右键 / Alt+左键
    2.视角缩放:滚轮 / Alt+右键

    导航器
    1.按住Shift,点击中间的小方块,恢复方向
    2.点Y轴,顶视图
    3.点X轴,右视图
    4.点Z轴,前视图

    视野中心
    1.将某物体放置于世界中心:选中一个物体,长按住F键
    此时旋转视图,似是绕着物体旋转
    2.出生点:添加一个新物体,其位于视图中心。并不是(0,0,0)。

    透视和正交
    透视视图Perspective:近大远小
    正交视图Orthographic:等距视图Isometric,物体显示与距离无关
    在导航器下方的persp处调节。

    透视,广角设定:
    摄像机的广角Field默认为60°。广角越大,透视畸变太厉害。可以设为30~40°。

    物体操作

    Unity自带的基础模型

    • Cube,立方体
    • Sphere,球体
    • Capsule,胶囊体
    • Cylinder,圆柱体
    • Plane,平面

    旋转工具Rotate Tools
    在Unity中,顺时针旋转,对应方向参量为负方向
    逆时针旋转,对应方向参量为正方形
    此外,按住ctrl键旋转使其每次角增量为15°。

    缩放工具Scale Tools:
    *AF扩展插件:AfSimpleExtension
    扩展功能:
    1.输出物体的尺寸Scale

    2.聚焦到事业重心 G键

    3.快速切换正交视图与等距视图。

    模型操作

    网格Mesh:存储了模型的形状数据(面,顶点坐标,法向坐标等)。
    材质Material:需添加到物体上,定义了物体的表面细节(颜色,是否金属,粗糙程度,是否透明…)
    纹理Textures:需添加到材质上,可以是贴图。

    在这里插入图片描述

    模型建好以后一般导出为 fbx文件格式。

    在Unity中,

    • 一个平面是没有厚度的
    • 正面可见,背面透明

    或者说,平面的背面不会被渲染

    ※ FBX文件的使用方式:
    1.材质替换

    • 选中 *.fbx 文件
    • 在Inspector 中切到 Materials属性—>Use Embeded Materials,On Demand Remap:映射新的材质
    • 点Apply 应用

      2.使用外部材质 Use External Materials
    • 选中fbx文件
    • Location:Use External Materials使用外部材质
    • 点Apply应用,将内嵌材质解压缩到Materials目录下
    • 直接修改Materials目录下的材质文件。

    资源文件

    资源文件:Assets目录下的文件,被称为资源。
    常见类型:

    • 模型文件Model *.fbx
    • 图片文件Texture *.jpg/png/psd/tif
    • 音频文件AudioClip *.mp3/wav/aiff
    • 脚本文件Script *.cs
    • 材质文件,场景文件 *.mat,*.unity

    轴心,父子关系,空物体
    Global全局坐标系:绝对坐标,其X Y Z 指向世界的上下东西南北

    Local本地坐标系:相对坐标,其X Y Z 指向模型的前后左右上下

    坐标轴的含义:

    • X:Right 向右
    • Y:up 向上
    • Z:forward 向前,一般要求模型直面与Z轴方向一致。

    组件Component

    常见组件

    • Light:光照
    • Mesh Filter:网格过滤器,加载网格数据
    • Mesh Renderer:网格渲染器,无渲染物体无法显示

    组件的增添与删除…

    AudioSource组件的使用方式:
    1.添加一个音乐文件 *.mp3/wav/aiff
    2.创建一个物体

    • Add Component,Audio | Audio Source
    • 将音乐文件拖到AudioSource.AudioClip属性
    • 在3D窗口上方选 Toggle Audio On

    Transform变换组件

    • Position:方位
    • Rotation:旋转
    • Scale:尺寸

    摄像机组件
    实用操作
    Align with View:调整摄像机角度使其与3D视图对齐。

    预制体简述
    预制体:预先规定好信息的一些游戏对象。以便于下次使用。
    一些细节:

    • 预制体导出时需要勾选其依赖(材质,脚本等),否则无法正常使用。
    • 预制体仅仅记录了结点信息
    • prefab不包含材质贴图数据,仅包含引用

    脚本与编程

    给游戏对象挂载脚本的步骤

    • 创建Scripts文件夹,在其中创建一个C#文件
    • 进入C#,编写代码,并保存
    • 将脚本文件挂载到游戏对象中(拖拽 or AddComponent)即可

    Tips:

    • C#文件名必须和类名一致,否则无法挂载
    • 脚本必须被挂载到物体上,才会被调用

    常用的信息代码

    GameObject obj = this.gameObject; //获取到当前脚本挂载游戏对象
    string name = obj.name; //获取到游戏对象名字
    Transform tr = obj.transform; // 获取到Transform属性
    Vector3 pos = tr.position; //获取到Transfrom中的position值(返回值是三维向量)
    
    Debug.Lo("物体当前的位置:"+pos.ToString("F3")); //保留三位小数
    
    //世界坐标和本地坐标
    //this.gameObject.transform 可等效写为 this.transform
    tr.localPosition; //本地坐标
    tr.position; //世界坐标
    
    
    //修改某物体的坐标
    this.transform.localPosition = new Vector3(1.5f, 2.5f, 0);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    帧更新与物体运动
    C#代码中的Update()方法:

    void Update()
        {
            //Debug.Log("帧更新 Time:" + Time.time); // 获取游戏时间,测试帧率
            //Debug.Log("帧更新 时间差:" + Time.deltaTime); // 每次刷新的时间差
            
            //物体移动
            //设置小车运动的速度
            float speed = 100;
            float distance = speed * Time.deltaTime;
            Vector3 pos = this.transform.localPosition;
            pos.z += distance;
            this.transform.localPosition = pos;
            
            //使用Translate方法实现物体移动
            this.transform.Translate(0, 0, distance);
            
            //dx,dy,dz分别为三个方向的增量,space可选择相对于哪个坐标系
            this.transform.Translate(dx,dy,dz,space);
            //例子
            this.transfrom.Translate(distance,0,distance,Space.Self/World)
            
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    物体转向

    void Start()
    {
        //转向(在途中加入一个红旗,获取到红旗方向,让小车向红旗方向运行)
        GameObject flag = GameObject.Find("红旗");
        this.transform.LookAt(flag.transform);
    }
    
    void Update(){
        float speed  = 100;
        float distance = speed * Time.deltaTime;
        
        this.transform.Translate(0,0,distance,Space.Self);
    }
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    小练习:当车到达旗子时,停止运动

    public class SimpleLogic : MonoBehaviour
    {
        GameObject flag;
        // Start is called before the first frame update
        void Start()
        {
            flag = GameObject.Find("红旗");
            this.transform.LookAt(flag.transform);
        }
    
        // Update is called once per frame
        void Update()
        { 
            //让小车到达红旗时停下来
            Vector3 p1 = this.transform.position;
            Vector3 p2 = flag.transform.position;
            Vector3 p = p2 - p1;
            //求得两个向量的模值
            float length1to2 = p.magnitude;
    
            if (length1to2 >= 30)
            {
                //设置小车运动的速度
                float speed = 100;
                float distance = speed * Time.deltaTime;
    
                this.transform.Translate(0, 0, distance, Space.Self);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    物体的旋转
    方式一:采用传统的改Rotation值的方式

    //不易操作,官方不建议使用
    transform.rotation=...
    
    //建议使用欧拉角的方式
    
    • 1
    • 2
    • 3
    • 4

    方式二:采用欧拉角的计算方法

    transform.eulerAngles = new Vector3(0,45,0)
    transform.localEulerAngles = new Vector3(0,45,0);
    
    • 1
    • 2

    案例:将游戏对象 风扇 转起来
    方案一:使用传统欧拉角

    void Update()
        {
            //旋转速度(1800°/s)
            float rotateSpeed = 1800;
            float rotateValue = rotateSpeed * Time.deltaTime;
    
            Vector3 angles = this.transform.localEulerAngles;
    
            angles.y += rotateValue;
    
            this.transform.localEulerAngles = angles;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    方案二:使用Rotate() API直接调用

    void Update(){
        //设置旋转速度
        float rotateSpeed = 1800;
        
        this.transform.Rotate(0,rotateSpeed * Time.deltaTime,0,Space.Self);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    脚本与编程的实质

    //unity框架会自动创建游戏对象为一个结点
    GameObject obj = new GameObject();
    //紧接着创建该游戏结点下挂载的脚本,并由框架挂载到该游戏结点下
    SimpleLogic sl = new SimpleLogic();
    //并由Unity自动调用Start和Update方法实现初始化和帧更新
    
    • 1
    • 2
    • 3
    • 4
    • 5

    消息函数
    在c#语言中,所有的脚本类都 应该继承于 MonoBehavior 类,其作用类比于Java中的 Object 类。
    消息函数(事件函数):是指一些回调函数。比如Start()方法会在脚本初始化的时候被调用,而Update()会在帧更新的时候被调用。

    常见的消息函数:

    • Awake:初始化,仅执行一次,组件被禁用时也会调用
    • Start:初始化,仅执行一次,组件被禁用时不会调用
    • Update:帧更新,每帧调用一次
    • OnEnable:当组件启用的时候调用
    • OnDisable:当组件禁用时被调用

    脚本的执行顺序

    • 脚本的执行顺序与Hierarchy中层级顺序无关
    • 一般的,可以在Project Setting中的Scripts Execution Order中设置脚本执行的优先级。但没必要!!!

    脚本参数

    给脚本添加一个参数:

    [ Tooltip("这个是Y轴向的角速度") ]
    public float rotateSpeed = 30f;
    //在Unity中,脚本参数多了一栏Rotate Speed,值为30
    
    • 1
    • 2
    • 3

    注意事项:

    • 修饰符必须为 public
    • 参数名称必须采用驼峰式命名
    • 可采用Tooltip给参数名称添加解释
    • 代码中的规定数值为参数的默认值,通过reset按钮可重置

    值类型和引用类型
    值类型:

    • 值类型本身是一个值,可直接赋值,若未赋值,则默认为0
    • 不能为null

    结构体类型:

    • 本质也是值类型,不能设置为null
    • 设置初始值时必须采用new的方式
    • 典例:Vector3
    public int intValue ; //0
    public float floatValue = 0.5f;
    public bool boolValue = true;
    public string stringValue = "Hello C-Sharp";
    public Vector3 rotateSpeed = new Vector3(1,1,1);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    引用类型:
    案例:如果一个平面内有两个红旗,我们需要手动规定小车向哪个红旗移动,就可以采用引用类型的属性

    public GameObject target; //目标物体
    
    void Start (){
        this.transform.LookAt(target.transform);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    注意:一定要给引用类型赋值,否则会报 空指针异常

    鼠标的输入

    旋转飞车实例:

    void Update()
        {
            /*
                0:鼠标左键
                1:鼠标右键
                2:鼠标中键
             */
            if (Input.GetMouseButtonDown(0))
            {
                Debug.Log("鼠标按下");
                rotateSpeed = 900f;
                moveSpeed = 300f;
            }
            if (Input.GetMouseButtonUp(0))
            {
                Debug.Log("鼠标抬起");
                rotateSpeed = 0f;
                moveSpeed = 0f;
            }
            this.transform.Rotate(0, rotateSpeed * Time.deltaTime, 0, Space.Self);
            this.transform.Translate(0, 0, moveSpeed * Time.deltaTime, Space.World);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    相关API:

    • GetMouseButtonDown:鼠标按下
    • GetMouseButtonUp:鼠标抬起
    • GetMouseButton:状态探测,只要鼠标按下,会一直调用。

    旋转飞车实例2:

    void Update()
        {
            /*
                0:鼠标左键
                1:鼠标右键
                2:鼠标中键
             */
            if (Input.GetMouseButton(0))
            {
                rotateSpeed = 900f;
                moveSpeed = 300f;
            }
            else
            {
                rotateSpeed = 0;
                moveSpeed = 0;
            }
            this.transform.Rotate(0, rotateSpeed * Time.deltaTime, 0, Space.Self);
            this.transform.Translate(0, 0, moveSpeed * Time.deltaTime, Space.World);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    &一些补充的工具函数

    //获取到鼠标点击的位置坐标
    Vector3 mousePos = Input.mousePosition;
    //获取到屏幕的尺寸
    int screenWidth = Screen.width;
    int screenHeight = Screen.height;
    
    //获取物体的屏幕坐标
    Vector3 pos = this.transform.position;
    Vector3 screenPos = Camera.main.WorldToScreenPoint(pos);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    键盘的输入

    常用API:

    • Input.GetKeyDown(key):按键事件,按下
    • Input.GetKeyUp(key):按键事件,抬起
    • Input.GetKey(key):案件状态,是否正被按下

    代码来操作组件

    操作AudioSource组件

    //获取到AudioSource组件(泛型)
    AudioSource audio = this.GetComponent();
    //播放
    audio.Play();
    
    • 1
    • 2
    • 3
    • 4

    引用别的组件
    应用场景:在主控结点中操作背景音乐的组件

    public class MainLogic : MonoBehaviour
    {
        //public GameObject bgmNode;
        //引用扬声器组件
        public AudioSource bgm;
        //引用脚本组件
        public FanLogic fan;
        //风扇转速
        public float rotateSpeed;
        
        void Start(){
            //AudioSource audio = bgmNode.GetComponent();
            //audio.Play();
            bgm.Play();
        }
        
        void Update(){
            if(Input.GetMouseButtonDown(0))
            {
                rotateSpeed = 800;
                //旋转代码在FanLogic脚本下 
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    获取物体API

    案例:主控结点下找到无人机目录下的旋翼对象,并调用它的脚本组件

    //主控结点
    //方式二:(在Unity中拖入)
    public GameObject wingNode;
    //方式一:
    void Start(){
        GameObject node = GameObject.Find(无人机/旋翼);
        RotateLogic rotateLogic = node.GetComponent();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    获取游戏节点的父级与子级:

    //获取当前组件的父结点与父方位
    Transform parent = this.transform.parent;
    GameObject parentNode = this.transform.parent.gameObject;
    
    //获取子结点的方位
    //方式一:通过foreach遍历
    foreach (Transform child in transform)
    {
        Debug.Log("子物体" + child.name); //child
    }
    
    //方式二:通过GetChild()索引API
    Transform child = this.transform.GetChild(0);
    
    //方式三:通过名字查找子项
    Transform child = this.transform.Find("子项名或路径");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    给物体设置新的父级:

    this.transform.SetParent(null/GameObject);
    
    • 1

    切换物体的显示状态:

    Transform child = this.transform.Find("xxx");
    if(child.gameObject.activeSelf)
    {
        //隐藏
        child.gameObject.SetActive(false);
    }
    else
    {
        //显示
        child.gameObject.SetActive(true);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    资源的使用API

    用户按下A,D键播放音效成功与失败

    //成功音效
    public AudioClip audioSuccess;
    //失败音效
    public AudioClip audioFail;
    
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            AudioSource audio = GetComponent();
            audio.PlayOneShot(audioSuccess);
        }
        if (Input.GetKeyDown(KeyCode.D))
        {
           AudioSource audio = GetComponent();
           audio.PlayOneShot(audioFail);
        }
    }
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    制作随机音乐盒程序

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class MusicBox : MonoBehaviour
    {
        public AudioClip[] songs;
        
        // Start is called before the first frame update
        void Start()
        {
            if (songs == null || songs.Length == 0)
            {
                Debug.Log("当前歌单列表为空!");
            }
        }
    
        // Update is called once per frame
        void Update()
        {
            if (Input.GetKeyDown(KeyCode.Space))
            {
                NextSong();
            }
        }
    
        private void NextSong()
        {
            //随机播放
            int randomIndex = Random.Range(0, songs.Length);
    
            //取到AudioSource组件
            AudioSource audio = GetComponent();
    
            audio.clip = this.songs[randomIndex];
            audio.Play();
            Debug.Log("正在播放第" + (randomIndex+1) + "首歌,歌名为:" + audio.clip.name);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    定时调用与线程

    Unity是单线程核心,暂时不必考虑线程,调度,并发。

    //延迟调用API
    this.Invoke("函数名",延迟时间);
    
    //循环调用API
    this.InvokeRepeating("函数名",循环时间间隔);
    
    //查看当前线程的ID
    int ThreadId = Thread.CurrentThread.ManagedThreadId;
    
    //判断函数是否正在被调用
    bool isInvoking = IsInvoking("函数名");
    //取消该函数的调用
    CancelInvoke("函数名");
    //取消当前脚本所有Invoke调用
    CancelInvoke();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    向量的基本运算

    //定义一个三维向量
    Vector3 v1 = new Vector3(3,0,4);
    //求向量的模长
    float length = v1.magnitude;
    //向量标准化
    Vector3 v2 = v1.normalized;
    
    //物体运动的优化写法
    //定义一个三维向量来表示不同方向的速度
    public Vector3 speed;
    
    //优化物体移动写法
    void Update()
    {
         this.transform.Translate(speed * Time.deltaTime,Space.Self);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    预制体与实例

    通过API创建实例

    • 首先准备子弹的预制体prefab
    • 添加火控脚本 FireLogic.cs
    //子弹预制体
    public GameObject bulletPrefab;
    //子弹目录
    public Transform bulletFolder;
    //子弹出生点
    public Transform firePoint;
    //炮塔的引用(为了获取到炮塔发射子弹的方向)
    public Transform cannon;
    
    void Update()
    {
        //创建实例
        GameObject node = Object.Instantiate(bulletPrefab,bulletFolder);
        //指定出生点
        node.transform.position = this.firePoint.position;
        //指定初始角度
        node.transform.localEulerAngles = this.cannon.eulerAngles;
        //子弹脚本参数的设置(子弹飞行速度)
        node.GetComponent().setSpeed(0.5f);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 销毁子弹
    //销毁自身结点的API
    Object.Destroy(this.gameObject);
    //注意不要写错,写为⬇,该写法是销毁组件,而并非结点
    Object.Destroy(this);
    
    • 1
    • 2
    • 3
    • 4

    物理系统与组件

    刚体组件

    Physic—>RigidBody:刚体组件
    常用属性:

    • Mass:质量
    • Drag:摩擦力
    • AngularDrag:角摩擦力

    Physic—>Collider:碰撞模型
    常用类型:BoxCollider,SphereCollider

    物理材质Phsicas Material:

    • 在Assets中添加一个Physics Material
    • 在里面设置全局性的摩擦力Friction,弹性系数等等

    碰撞检测
    实现 碰撞检测的步骤:

    • RigidBody–>is Kinematic 勾选标记为 运动学刚体
    • Collider–>is Tragger 勾选 标记为触发器
    • 挂一个脚本,添加消息函数⬇
    void OnTriggerEnter(Collider other)
    {
        //拿到被碰撞物体的名字
        string name = other.name;
        //销毁被碰撞物体
        Object.Destroy(other.gameObject);
        Object.Destroy(this.gameObject);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3D 射击游戏实战

    • 1.导入模型
    • 2.更改天空盒
      Window--->Rendering--->lighting--->environment--->Skybox Material
    • 3.添加子弹,模型,材质,脚本等
    • 4.给子弹和怪兽添加碰撞检测
    • 5.子弹的自动发射,自毁与预制体
    • 6.玩家的按键操作
    • 7.怪兽的走位移动
    • 8.怪兽生成器
    • 9.子弹和爆炸特效

    源码展示
    子弹BulletLogic:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    /*
        子弹相关逻辑:
            准备工作:子弹的预制体以及导入工程
            1.子弹的Z轴移动
            2.子弹的自毁
            3.子弹的特效导入
     */
    public class BulletLogic : MonoBehaviour
    {
        //设置子弹的运动速度
        [Tooltip("子弹飞行速度")]
        public Vector3 speed;
        [Tooltip("子弹飞行时长")]
        public float lifetime = 5f;
        [Tooltip("子弹爆炸特效预制体")]
        public GameObject explosionEffect;
    
        // Start is called before the first frame update
        void Start()
        {
            Invoke("SelfDestroy", lifetime);
        }
    
        // Update is called once per frame
        void Update()
        {
            this.transform.Translate(speed, Space.Self);
        }
    
        //触发器函数
        private void OnTriggerEnter(Collider other)
        {
            Debug.Log("发生碰撞了");
            //如果碰撞到怪兽
            if (!other.name.StartsWith("怪兽")) return;
            
            Destroy(this.gameObject);
            Destroy(other.gameObject);
    
            //创建一个爆炸粒子特效对象
            GameObject node = Object.Instantiate(explosionEffect,null);
            node.transform.position = this.transform.position;
            //当粒子特效播放完成时自动销毁
        }
    
        //子弹自毁函数
        private void SelfDestroy()
        {
            Debug.Log("子弹已自毁");
            Destroy(this.gameObject);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    玩家PlayerLogic:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    /*
        玩家相关逻辑:
            准备工作:导入玩家模型的预制体资源
            1.设置子弹发射点,并实现从该点定时发射子弹
            2.添加玩家的按键控制移动
     */
    public class PlayerLogic : MonoBehaviour
    {
        //预制体资源
        public GameObject bulletPrefab;
        //子弹生成目录
        public Transform bulletFolder;
        //子弹发射点
        public Transform firePoint;
        //子弹发射间隔
        public float fireInterval;
        //玩家移动速度
        public float playerSpeed;
    
        // Start is called before the first frame update
        void Start()
        {
            InvokeRepeating("fire", fireInterval, fireInterval);
        }
    
        // Update is called once per frame
        void Update()
        {
            float speedX = 0;
            //按键控制
            if (Input.GetKey(KeyCode.A))
            {
                speedX = -playerSpeed;
            }
            else if (Input.GetKey(KeyCode.D))
            {
                speedX = playerSpeed;
            }
            else
            {
                speedX = 0;
            }
            this.transform.Translate(speedX * Time.deltaTime, 0, 0, Space.Self);
            
        }
    
        //发射子弹的函数
        private void fire()
        {
            //生成一个子弹实例
            GameObject bullet = Object.Instantiate(bulletPrefab, bulletFolder);
            //设置子弹的出生点
            bullet.transform.position = this.firePoint.position;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    怪兽EnemyLogic:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    /*
        怪兽相关逻辑:
            准备工作:导入怪兽的预制体进工程
            1.水平速度的蛇皮走位逻辑
            2.前后速度的固定逻辑
     */
    public class EnemyLogic : MonoBehaviour
    {
        //水平速度
        float speedX = 0;
        //前后速度
        public float speedZ;
    
        // Start is called before the first frame update
        void Start()
        {
            //重复周期调用蛇皮走位
            InvokeRepeating("move", 0.1f, 0.5f);
        }
    
        // Update is called once per frame
        void Update()
        {
            this.transform.Translate(speedX * Time.deltaTime, 0, speedZ * Time.deltaTime, Space.Self);
        }
    
        //怪兽的蛇皮走位
        private void move()
        {
            //设置一个随机速度数组
            float[] speed = { -5, -10, -20,-30, 5, 10, 20 ,30};
            //随机选取一个速度作为水平速度
            int rnum = Random.Range(0, speed.Length);
            //设置速度
            speedX = speed[rnum];
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    怪兽生成器EnemyCreator:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    /*
        怪兽生成器相关逻辑:
            1.定时生成怪兽即可
     */
    public class EnemyCreator : MonoBehaviour
    {
        //要创建的怪兽预制体
        public GameObject enemyPrefab;
        //创建怪物间隔时长
        public float enemyInterval = 0.5f;
        
    
        // Start is called before the first frame update
        void Start()
        {
            InvokeRepeating("creatEnemy", 0.1f, enemyInterval);
        }
    
        // Update is called once per frame
        void Update()
        {
            
        }
    
        private void creatEnemy()
        {
            GameObject node = GameObject.Instantiate(enemyPrefab, this.transform);
            node.transform.position = this.transform.position;
    
            //调整随机出生点
            int rnum = Random.Range(-50, 50);
            node.transform.Translate(rnum, 0, 0, Space.Self);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    恭喜未来的游戏开发工程师,正式入门!!!后会有期!!!

  • 相关阅读:
    这就叫速度,并发编程深度解析实战七天杀上 GitHub 榜首
    记一次阿里云oss文件上传服务假死
    【Unity Shader】屏幕后处理4.0:基于高斯模糊的Bloom
    总结线程池
    南京理工大学计算机考研资料汇总
    vue2技能树(1)
    宿舍管理系统现代化:Spring Boot技术实践
    栈与队列练习题
    新手怎么做小说推文和短剧推广怎么申请授权
    2022年高教社杯国赛赛题浅评
  • 原文地址:https://blog.csdn.net/qq_55071342/article/details/126122671