《shooting game》学习笔记

#《shooting game》Unity小游戏 学习笔记

  • scene

    场景视图:主要吧Hierarchy视图中的模型进行设计,摆放的区域
    游戏视图:展示效果的区域
    层次视图:Hierarchy主要存放游戏场景中具体使用的项目对象,比如摄像机,贴图等
    项目视图:主要放所有的资源文件。比如脚本,预设,材质,动画
    检查视图:Inspector可以理解为对项目中所有空间属性修改,设置的地方

  • Materials

    Unity中材质Material:指色彩Main Color,纹理Texture,着色器shader(光滑度,透明度,反射率,折射率,发光度)等。因为预览方式是个球体,有时又被称作材质球。

    Unity中赋予材质Material:将材质赋予给游戏物体Gameobject的Mesh Renderer组件,操作为直接从项目面板拖动到Element 0上。一种快捷方式是直接把材质拖拽到Scene场景面板或者Hierarchy面板上的游戏物体上。

  • Shader

    Shader(着色器)实际上就是一小段程序,它负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作用,然后输出。绘图单元可以依据这个输出来将图像绘制到屏幕上。输入的贴图或者颜色等,加上对应的Shader,以及对Shader的特定的参数设置,将这些内容(Shader及输入参数)打包存储在一起,得到的就是一个Material(材质)。之后,我们便可以将材质赋予合适的renderer(渲染器)来进行渲染(输出)了。

    注:Shader不能直接拖拽到游戏物体上,需要我们先新建一个Material,然后把Shader赋予给Material,再把Material赋予给游戏物体。有些Shader还需要把对应的C#脚本赋予给游戏物体。

  • Animation

  • Prefab

    可以理解为是一个游戏对象及其组件的集合,目的是使游戏对象及资源能够被重复使用。相同的对象可以通过一个预设体来创建,此过程可理解为实例化。

    存储在项目文件中(Project视图)的状态时,预设体作为一个资源,可应用在一个项目中的不同场景中。当拖动预设体到场景中就会创建一个实例。该实例与其原始预设体的有关联的,对预设体进行更改,实例会同步修改。Prefab可以提升资源的利用率和开发的效率。

  • AudioSource

    AudioSource 是 Unity 中的 Audio 组件,其主要用来播放游戏场景中的 AudioClip,AudioClip 就是导入到 Unity 中的声音文件。Unity 可导入的音频文件格式有 .aif,.wav,.mp3和.ogg。此外,Audio Source 还可以设置一些播放声音的效果,增强游戏场景中的声音效果。

    AudioListener 是游戏中的声音接收器,一般位于 Main Camera 游戏对象上,它可以接收游戏中的所有音乐和音效(只要其所附加的游戏物体在音效的影响范围内),此外,每一个 Scene 中仅有一个 Audio Listener

    添加路径:首先选中 AudioSourceObj 游戏对象,然后在 Inspector 面板下方点击 Add Component -> Audio -> Audio Source

  • Collider(碰撞器与Tirgger(触发器))

    Box Collider是一个立方体外形的基本碰撞体,该碰撞体可以调整为不同大小的长方体,可以做门,墙等

  • Rigidbody(刚体)

    刚体能让你的游戏对象被物理引擎所控制,它能通过受到推力和扭力来实现真实的物理表现效果。所有游戏对象必须包含刚体组件来实现重力、通过脚本施加力、或者与其他对象进行交互,这一切都通过NVIDIA的PhysX物理引擎来实现。

    碰撞器(Collider)不需要刚体(Rigidbody)
    刚体(Rigidbody)要发生碰撞,一定需要碰撞器(Collider)
    碰撞器决定了碰撞发生时的边界条件
    刚体决定了碰撞发生后的物体的运动效果
    没有碰撞器的刚体,会在物理模拟中相互穿透。

  • tag

    Tag 标签,就是一个标签。标签可以起到标识,区分的作用。
    同一类的模型,我们可以根据需要给他们设置成统一的标签。

    可以选中一个模型,在模型的Inspector 面板上的顶部位置,设置Tag 选项为一个
    具体的标签。
    如果说引擎提供的标签没有自己想要的标签,可以自己手动添加新标签。


代码细节

一.移动

  • Palyer移动

        float movev = 0;//纵向
        float moveh = 0;//水平移动距离
        //上下左右
        if (Input.GetKey(KeyCode.UpArrow))
            movev -= m_speed * Time.deltaTime;
        if (Input.GetKey(KeyCode.DownArrow))
            movev += m_speed * Time.deltaTime;
        if (Input.GetKey(KeyCode.LeftArrow))
            moveh += m_speed * Time.deltaTime;
        if (Input.GetKey(KeyCode.RightArrow))
            moveh -= m_speed * Time.deltaTime;
        //移动
        this.m_transform.Translate(new Vector3(moveh, 0, movev));
    

    Input是一个包含了输入功能的类,包括几乎所有的键盘鼠标或触控操作函数。

    Time,deltaTime 表示每帧的经过时间,那些需要每帧做增减变动的数值都需要乘于它。

    this.transform 调用的是游戏体的Transform组件,Transform组件提供的主要功能都是和移动,旋转,缩放游戏体有关的。其中Vector3类型,用来表示x,y,z三个方向上的移动距离。

  • Enemy移动

    protected virtual void UpdatedMove()
    {
        float rx = Mathf.Sin(Time.time) * Time.deltaTime;//左右移动
        m_transform.Translate(new Vector3(rx, 0, -m_speed * Time.deltaTime));
    }
    

    UpdateMove 函数用来执行敌人的移动,使用了Sin函数使数值在-1~1之间循环变化,敌人就会左右迂回移动。

二.生成

  • 发射子弹

        m_rocketRate -= Time.deltaTime;
        if (m_rocketRate <= 0)
        {
            m_rocketRate = 0.1f;
            if (Input.GetKey(KeyCode.Space) || Input.GetMouseButton(0))
            {
                Instantiate(m_rocket, m_transform.position, m_transform.rotation);
                //射击音效
                m_audio.PlayOneShot(m_shoopClip);
            }
        }
    

    在这里插入图片描述

    Instantiate函数实例化是将original对象的所有子物体和子组件完全复制,成为一个新的对象。这个新的对象拥有与源对象完全一样的东西,包括坐标值等。
    original:用来做复制操作的对像物体,源对象
    position:实例化的对象的位置坐标
    rotation:实例化的对象的旋转坐标(旋转四元数)
    parent:实例化对象的父对象,就是给这个实例化对象找的爹,在完成实例化函数处理后,实例化对象将在父对象下,是父对象的子对象
    instantiateWorldSpace(老的叫WorldSpaceStays):这个值为TRUE,表示实例化对象相对于世界坐标系的位置(是位置,不是坐标值,比如实例化前在Canvas左上角,实例化后还在左上角)不变,相对于父对象的坐标值变了。为false,表示实例化对象相对于父对象的坐标值不变,但在世界坐标系中的位置变了。

    PlayOneShot()在AudioSource 声源(即声音发出的来源)处播放 2D 音效

  • enemy子弹

    void Awake()
    {
        GameObject obj = GameObject.FindGameObjectWithTag("Player");
        if (obj != null)
            m_player = obj.transform;
    }
    
        m_fireTimer -= Time.deltaTime;
        if(m_fireTimer<=0)
        {
            m_fireTimer = 2;
            if(m_player!=null)
            {
                Vector3 relativePos = m_transform.position - m_player.position;
                Instantiate(m_rocket, m_transform.position, Quaternion.LookRotation(relativePos));
            }
        }
    

    Awake方法继承于MonoBehaviour,它会先于start方法在游戏体实例化时执行一次。这里是使用FindGameObjectWithTag函数获得主角的游戏体实例。

    Quaternion.LookRotation使子弹在初始化时朝向主角方向。

三.触发

  • enemy碰撞

    void OnTriggerEnter(Collider other)
    {
        if (other.tag.CompareTo("PlayerRocket") == 0)
        {
            Rocket rocket = other.GetComponent<Rocket>();
            if (rocket != null)
            {
                m_life -= rocket.m_power;
                if (m_life <= 0)
                    Destroy(this.gameObject);
            }
        }
        else if (other.tag.CompareTo("Player") == 0)
        {
            m_life = 0;
            Destroy(this.gameObject);
        }
        if (other.tag.CompareTo("bound") == 0)
        {
            m_life = 0;
            Destroy(this.gameObject);
        }
    }
    

    OnTriggerEnter函数,派生于MonoBehaviour,在碰撞体相互接触时触发

    other.tag.CompareTo(“PlayerRocket”) == 0 语句用来比较字符串,判断遇到的碰撞体是否是PlayerRocket。

    Rocket rocket = other.GetComponent()语句获得了对方碰撞体的Rocket脚本组件。

    other.tag.CompareTo(“Player”) == 0语句用来判断遇到的碰撞体是否是Palyer,如果是则直接销毁自身。

  • 声音与特效

    public AudioClip m_shoopClip;//开火声音
    protected AudioSource m_audio;//声音源
    public Transform m_explosionFX;//爆炸特效
    

    Instantiate(m_explosionFX, m_transform.position, Quaternion.identity);

    m_audio.PlayOneShot(m_shoopClip);

优化

  • this.transform重复调用

    protected Transform m_transform;
    void Start()
        m_transform = this.transform;
    

    Update函数中每帧都调用this.transform组件,会造成效率问题。可以在对象初始化时只调用一次并且保存起来。Start 函数会在对象被实例化时自动调用一次,类似构造函数。

  • 销毁

    void Start()
    {
        m_transform = this.transform;
        Destroy(this.gameObject, m_liveTime);
    }
    

    在子弹生成之初就定义何时销毁,降低游戏负荷

    if (other.tag.CompareTo("bound") == 0)
    {
        m_life = 0;
        Destroy(this.gameObject);
    }

创建一个大于游戏场景的不可视的围墙tag为“bound”,敌人碰撞就会销毁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值