3D游戏编程作业(一)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/sodifferent/article/details/100592006

1.简答题

(1)解释游戏对象(GameObjects) 和 资源(Assets)的区别与联系。
游戏对象是在游戏中真实存在一个物体,是可以进行选中操作的对象,而资源则是对游戏对象的一个修饰,比如一个正方体是游戏对象,但是其表面的图案等具体信息是资源来设定的。

(2)下载几个游戏案例,分别总结资源、对象组织的结构(指资源的目录组织结构与游戏对象树的层次结构)
在unity中的游戏其资源的目录结构一般有脚本和各种材质包,对不同的对象使用的类型相似的放在一起,比如颜色放一起,材质放一起等等。
对于对象组织的目录结构一般为从属结构,对某一些对象的控制,对资源环境的控制等等。

(3)编写一个代码,使用 debug 语句来验证 MonoBehaviour 基本行为或事件触发的条件
基本行为包括 Awake() Start() Update() FixedUpdate() LateUpdate()
常用事件包括 OnGUI() OnDisable() OnEnable()
首先使用C#语言编写脚本文件

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

public class NewBehaviourScript : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("start\n");
    }

    // Update is called once per frame
    void Update()
    {
        Debug.Log("update\n");
    }
    private void Awake()
    {
        Debug.Log("awake\n");
    }
    private void FixedUpdate()
    {
        Debug.Log("fixedupdate\n");
    }
    private void LateUpdate()
    {
        Debug.Log("lateupdate\n");
    }
    private void OnGUI()
    {
        Debug.Log("ongui\n");
    }
    private void OnDisable()
    {
        Debug.Log("ondisable\n");
    }
    private void OnEnable()
    {
        Debug.Log("onenable\n");
    }
}

所以其是否执行只需要观察是否有相应输出即可。
程序运行结果如下:
在这里插入图片描述
可以看到在程序最开始运行时会调用Awake函数,然后调用Onenable,接着执行Start函数,然后FixedUpdate,这些执行完之后才开始Update函数。
在这里插入图片描述
所以总结一下,同时查阅相关资料:
Awake函数:当脚本被载入时调用。
Start函数:第一次进入游戏时调用。
FixedUpdate函数:游戏循环时调用。
Update函数:当start函数执行完后进入游戏循环调用。
LastUpdate函数:当所有Update函数调用完之后调用。
OnGUI函数:游戏循环在渲染过程中,场景渲染之后调用。
OnDdiable函数:当某物体被禁用时调用。
OnEnable函数:当取消禁用时调用。

(4)查找脚本手册,了解 GameObject,Transform,Component 对象。
a.分别翻译官方对三个对象的描述(Description)
GameObject:是unity编辑中最重要的概念,在游戏中的每一个对象都是GameObject,从对象到道具到灯光,相机等。但是它本身不能做任何事情,在它成为一个角色之前需要给他一个特征、环境或者特殊的影响。
Transform:被用来储存一个游戏对象的位置、旋转角度、大小。每个GameObject都会有一个Transform组件依附。
Component:组件是游戏中对象和行为的螺母和螺栓,它们是每个游戏对象的功能部件。

b.描述下图中 table 对象(实体)的属性、table 的 Transform 的属性、 table 的部件
本题目要求是把可视化图形编程界面与 Unity API 对应起来,当你在 Inspector 面板上每一个内容,应该知道对应 API。
例如:table 的对象是 GameObject,第一个选择框是 activeSelf 属性。
第二个选择框是Transform,第三个选择框是MeshFilter,第四个是BoxCollider,第五个是MeshRenderer。

c.用 UML 图描述三者的关系(请使用 UMLet 14.1.1 stand-alone版本出图。
在这里插入图片描述
(5)整理相关学习资料,编写简单代码验证以下技术的实现:
a.查找对象:

Debug.Log("start\n");
        GameObject cube;
        cube = GameObject.Find("cube");
        if(cube!=null)
        {
            Debug.Log("find\n");
        }
        else
        {
            Debug.Log("did not find\n");
        }

在这里插入图片描述
运行结果如下
在这里插入图片描述

b.添加子对象

void Start()
    {
        Debug.Log("start\n");
        GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        cube.name = "cube1";
        cube.transform.position = new Vector3(0, Random.Range(0, 5), 0);
        cube.transform.parent = this.transform;
    }

运行结果如下:
在这里插入图片描述

c.遍历对象树

void Start()
    {
        Debug.Log("start\n");
        foreach (Transform child in transform)
        {
            Debug.Log(child.name);
        }
    }

目录结构如下:
在这里插入图片描述
运行结果如下:
在这里插入图片描述

d.清除所有子对象

void Start()
    {
        Debug.Log("start\n");
        foreach (Transform child in transform)
        {
            Destroy(child.gameObject);
        }
    }

目录结构如下:
在这里插入图片描述
运行结果如下:
在这里插入图片描述

(6)资源预设(Prefabs)与 对象克隆 (clone)
a.预设(Prefabs)有什么好处?
其为一种可重复使用的游戏对象,可以理解为一个配置好了的对象,可以很方便的加入到一个游戏中去,节省工作。而且在游戏中使用同一个预设都是它的一个克隆,当它本身改变时,其所有克隆出来的都会被改变。

b.预设与对象克隆 (clone or copy or Instantiate of Unity Object) 关系?
预设与克隆都可以对同一个对象复制出大量相同的对象,但是预设出来的克隆对象与其本体有关,当预设对象改变时,其所有克隆对象都会改变,但是如果通过克隆方式创建对象,那么创建出来的对象就与被克隆的对象没有了关系,可以随意更改。

c.制作 table 预制,写一段代码将 table 预制资源实例化成游戏对象

这里首先需要在Assets文件夹下创建一个Resources文件夹
在这里插入图片描述
然后再把cube对象拖进去。

void Start()
    {
        Debug.Log("start\n");
        GameObject cube1 = Instantiate(Resources.Load("cube") as GameObject);
        cube1.transform.parent = this.transform;
    }

对象目录如下:
在这里插入图片描述
运行之后结果如下:
在这里插入图片描述

编程实践,小游戏

游戏内容: 井字棋 或 贷款计算器 或 简单计算器 等等
技术限制: 仅允许使用 IMGUI 构建 UI
作业目的:
了解 OnGUI() 事件,提升 debug 能力
提升阅读 API 文档能力

下面是编写的井字棋游戏。
实现思路是主要在OnGUI函数中对整个游戏过程的控制,每次点击时都会判断当前该谁下了,当前位置是否可以下,是否有人获胜,获胜或者平局应该弹出什么,还有就是重新开始游戏。对于算法逻辑来说并不复杂,主要是对于一些函数的调用,实现代码如下:

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

public class NewBehaviourScript : MonoBehaviour
{
    private int[,] map = new int[3, 3];//创建棋盘
    private int turn = 0;
    private int num = 0;
    private int size = 50;

    // Start is called before the first frame update
    void Start()
    {
        num = 0;//下棋数
        turn = 1 - turn;//轮流下第一个
        for(int i=0;i<3;i++)
        {
            for(int j=0;j<3;j++)
            {
                map[i,j] = 0;
            }
        }
    }

    // Update is called once per frame
    void Update()
    {
        //Debug.Log("update\n");
    }

    private int getwin()
    {
        for(int i=0;i<3;i++)
        {
            if (map[i, 0] == map[i, 1] && map[i, 1] == map[i, 2]) return map[i, 1];
            if (map[0, i] == map[1, i] && map[1, i] == map[2, i]) return map[1, i];
        }
        if (map[1, 1] == map[0, 0] && map[1, 1] == map[2, 2]) return map[1, 1];
        if (map[1, 1] == map[0, 2] && map[1, 1] == map[2, 0]) return map[1, 1];
        if (num == 9) return 3;
        return 0;
    }

    private void OnGUI()
    {
        GUI.skin.button.fontSize = 20;
        GUI.skin.label.fontSize = 20;
        if (GUI.Button(new Rect(300, 250, 150, 50), "Reset"))
        {
            num = 0;
            turn = 1 - turn;//轮流下第一个
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    map[i, j] = 0;
                }
            }
        }

        int win = getwin();
        if(win==1) GUI.Label(new Rect(350, 50, 100, 50), "O wins");
        else if(win==2) GUI.Label(new Rect(350, 50, 100, 50), "X wins");
        else if(win==3) GUI.Label(new Rect(350, 50, 100, 50), "Draw");

        for (int i=0;i<3;i++)
        {
            for(int j=0;j<3;j++)
            {
                if(map[i,j]==1)
                {
                    GUI.Button(new Rect(i * size + 300, j * size + 100, size, size), "O");
                }
                else if(map[i,j]==2)
                {
                    GUI.Button(new Rect(i * size + 300, j * size + 100, size, size), "X");
                }
                else if(GUI.Button(new Rect(i * size + 300, j * size + 100, size, size), ""))
                {
                    if (win == 0)
                    {
                        if (turn == 0)
                        {
                            map[i, j] = 1;
                        }
                        else map[i, j] = 2;
                        turn = 1 - turn;
                        num++;
                    }
                }
            }
        }
    }

}

运行界面如下:
在这里插入图片描述
在这里插入图片描述
到这里就基本完成了要求。
视频文件如下井字棋

猜你喜欢

转载自blog.csdn.net/sodifferent/article/details/100592006