3D游戏编程学习笔记(二):认识游戏对象与资源

本文解析了Unity中游戏对象(GameObjects)与资源(Assets)的区别及联系,介绍了资源的目录组织结构与游戏对象树的层次结构,并展示了如何通过代码验证MonoBehaviour的行为触发条件。
摘要由CSDN通过智能技术生成

一、简答题

1. 解释游戏对象(GameObjects)和资源(Assets)的区别与联系

  • 游戏对象(GameObjects)
    首先我们我们来看一下Unity官方是怎么描述游戏对象的:

游戏对象是 Unity 中的基础对象,表示角色、道具和景物。它们本身并没有取得多大作为,但它们充当组件的容器,而组件可实现功能。为了向游戏对象提供成为光源、树或摄像机所需的属性,需要向游戏对象添加组件。根据要创建的对象类型,可以向游戏对象添加不同的组件组合。


Unity 拥有许多不同的内置组件类型,而且还可以使用 Unity Scripting API 来创建自己的组件。例如,通过将光源组件附加到游戏对象来创建光源对象。游戏中的每个对象(从角色和可收集物品到光源、摄像机和特效)都是游戏对象。但是,游戏对象本身无法执行任何操作;您需要向游戏对象提供属性,然后游戏对象才能成为角色、环境或特效。

  • 资源(Assets)
    我们再来看一下Unity官方是怎么描述资源的:

资源包集合了来自 Unity 项目或项目元素的文件和数据,Unity 将它们压缩并存储在一个扩展名为 .unitypackage 的文件中。与 zip 文件一样,资源包在解压缩后保持其原始目录结构,其中还包括资源的元数据(例如导入设置和指向其他资源的链接)。

  • 区别与联系
    从定义我们可以看出,资源是存储在Unity项目的Assets文件夹中的磁盘文件。纹理、3D模型以及音频等等都属于常见的资源。而对象是用于描述资源的特定实例的序列化数据集合。它可以是由Unity引擎所使用的任何类型的资源,例如上面所提到的纹理、3D模型以及音频。

2. 下载几个游戏案例,分别总结资源、对象组织的结构(指资源的目录组织结构与游戏对象树的层次结构)

资源的结构
请添加图片描述
由样例可以发现,project文件夹里分为Assets文件夹和Packages文件夹,Assets文件夹里又细分为Scenes文件夹、Scripts文件夹和Surface文件夹,这样可以根据资源文件的不同类型放入不同的文件夹中,便于资源的整理和利用


游戏对象的结构
请添加图片描述
由样例可以发现,游戏对象可以分为各种实体、摄像机、光源等环境的设置、玩家等等

3. 编写一个代码,使用debug语句来验证MonoBehaviour基本行为或事件触发的条件

代码如下:

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

public class new : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Start run!");
    }

    // Update is called once per frame
    void Update()
    {
        Debug.Log("Update run!");
    }

    void Awake()
    {
        Debug.Log("Awake run!");
    }

    void FixedUpdate()
    {
        Debug.Log("FixedUpdate run!");
    }

    void OnGUI()
    {
        Debug.Log("OnGUI run!");
    }

    void OnDisable()
    {
        Debug.Log("OnDisable run!");
    }

    void OnEnable()
    {
        Debug.Log("OnEnable run!");
    }
}

打开新项目,将脚本加入到Main Camera中,运行项目,控制台输出如下:
请添加图片描述
请添加图片描述
从运行结果可以看出,MonoBehaviour基本行为或事件触发的条件如下:

  • Start():在首次调用任何 Update 方法之前启用脚本时,在帧上调用 Start。
  • Update():如果启用了 MonoBehaviour,则每帧调用 Update。
  • FixedUpdate():MonoBehaviour.FixedUpdate 具有物理系统的频率;每个固定帧率帧调用该函数。
  • LateUpdate():如果启用了 Behaviour,则每帧调用 LateUpdate。
  • OnGUI():系统调用 OnGUI 来渲染和处理 GUI 事件。
  • OnDisable():该函数在行为被禁用时调用。
  • OnEnable():该函数在对象变为启用和激活状态时调用。

4. 查找脚本手册,了解GameObject,Tranform,Component对象

首先我们来看一下官方对于该三个对象的描述:

  • GameObject:Unity 场景中所有实体的基类。
  • Tranform:对象的位置、旋转和缩放。
  • Component:附加到 GameObject 的所有内容的基本类。

(图呢???)

5. 资源预设(Prefabs)与对象克隆(clone)

首先我们来思考这样一个问题,即预设(Prefabs)有什么好处?
在我们开发一些功能的时候,可以将一些能够复用的对象制作成预设件,可以将预设件存放到 Resources 目录之下,通过动态加载的方式加载到场景中并进行实例化。这样当我们需要大量使用某一游戏物体时,就避免重复的劳动,让我们开发游戏更加快捷。

如此看来,预制和克隆似乎是一致的,那么它们有什么区别呢?
答案就是克隆是将已经存在的游戏对象,或者是资源当中的预设进行复制。克隆可以是对已经添加在视图当中的游戏对象进行复制,也可以是对资源当中,我们提前预设好的模板进行克隆。因此,预设一般来说是克隆的一个基础步骤,在预设之后,就可以在资源当中随心所欲地为自己想要的对象进行克隆了。

(table在哪??写什么代码??)

二、编程实践——井字棋

  • 游戏内容:井字棋
  • 技术限制:仅使用IMGUI构建UI

代码实现如下:

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

public class Chess_1 : MonoBehaviour
{
    GUIStyle myStyle;
    private int turn = 1;
    private int num = 0;

    private int[,] matrix = new int[3,3];
    int middle=Screen.width / 2;

    void reset(){
        turn = 1;
        num = 0;
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                matrix[i,j]=0;
            }
        }
        print("game reseted.");
    }

    int check(){
        for(int i=0;i<3;i++){
            //列的检测
            if(matrix[i,0]!=0 && (matrix[i,0]==matrix[i,1] && matrix[i,0]==matrix[i,2])){
                return matrix[i,0];
            }
            //行的检测
            if(matrix[0,i]!=0 && (matrix[0,i]==matrix[1,i] && matrix[0,i]==matrix[2,i])){
                return matrix[0,i];
            }
        }
        //对角线检测
        if(matrix[0,0]!=0&&(matrix[0,0]==matrix[1,1]&&matrix[0,0]==matrix[2,2])){
            return matrix[0,0];
        }
        if(matrix[0,2]!=0&&(matrix[0,2]==matrix[1,1]&&matrix[0,2]==matrix[2,0])){
            return matrix[0,2];
        }
        if(num<9) return 0;
        return 3;
    }

    void result(int res){
        switch(res){
            case 0:
                if(turn == 1)
                    GUI.Box(new Rect(middle-45,55,100,35),"O's turn");
                else if(turn == 2)
                    GUI.Box(new Rect(middle-45,55,100,35),"X's turn");
                break;

            case 1:
                GUI.Box(new Rect(middle-45,55,100,35),"0 is Win!");
                break;

            case 2:
                GUI.Box(new Rect(middle-45,55,100,35),"X is Win!");
                break;
            case 3:
                GUI.Box(new Rect(middle-45,55,100,35),"Draw!");
                break;
        }
    }

    void click(int i,int j){
        matrix[i,j]=turn;
        num++;
        turn = (turn == 1) ? 2 : 1;
    }

    void OnGUI(){
        //游戏背景的box
        GUI.Box(new Rect(middle-120,30,252,330),"tic-tac-toe");
        //restart按钮
        if(GUI.Button(new Rect(middle-35,95,75,30),"Restart")){
            reset();
        }

        int res=check();
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                if(matrix[i,j]==1){
                    GUI.Button(new Rect(middle-120+i*84,135+j*70,84,70),"O");
                }
                if(matrix[i,j]==2){
                    GUI.Button(new Rect(middle-120+i*84,135+j*70,84,70),"X");
                }
                if(GUI.Button(new Rect(middle-120+i*84,135+j*70,84,70),"")){
                    click(i,j);
                }
            }
            result(res);
        }
    }



}
  • 首先是完善reset()函数,以及判断是否有三连的check()函数
  • result()函数接收check()函数的返回值,根据返回值来对局面进行判断,再通过OnGUI进行的渲染
  • click()函数负责点击行为的逻辑

将写好的C#脚本添加进Main Camera中运行,游戏效果如下所示:
请添加图片描述

三、参考资料

[1]. Unity官方手册
[2]. 3d学习笔记(一)——游戏对象与资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值