[更新中]Unity3D快速上手

Posted by

Unity快速开始

“基于 Game Objects and Scripts (catlikecoding.com),基于案例,缺乏系统性。

给看过教程的你,速查手册。

写一个像runoob一样能立刻上手的教程。自洽,精炼。

尝试回答问题,基于你熟悉的语言或工具,比如Python+PySide2(Qt5),从而快速理解Unity+C#。“如何做到xxx”,找到最佳实践,以及“为什么不做xxx”.

中英文恰当混用,省得啰嗦。”

本文目前能回答的问题:

  1. 创建一个3D的球体,涂成黄色,脚本控制它上下移动。
  2. 切换效率更高的URP来渲染3D
  3. 在这之前,绑定脚本和object
  4. 控制台打印Hello World
  5. 把Editor中的Objects组织成“文件夹”
  6. 脚本复制GameObjects

在包管理器 window/package里, 关掉VS code Editor和 Test Framework以外的,这就是最小环境了。Universal Render Pipeline (URP) 需要 Universal RP 包。TextMeshPro 包提供UI支持。

设置Color space 为linear,默认是gamma,位于 Project settings/Player/Other Settings/ Rendering::Color space。 默认Gamma只是为了兼容旧的设备。

默认主窗口布局:左边栏Hierarchy, 底边栏Project, Console,右边栏Inspector.

Create Game Object , 空的Game Object可用做文件夹。在Hierarchy创建。

在Hierarchy创建Object,在Project/Assets创建Material,把Material拖放到Object的Inspector的对应位置。Bang!有材质的3D实体出现了!

Create C# script in Project/Assets.

类可以create component in Unity:

public class Clock UnityEngine.MonoBehaviour{
    void Awake() {}
    void Update(){}
    void OnDisable(){}
}

Or

using UnityEngine; 
public class Clock:MonoBehaviour{}


使类成员在Unity界面显示并允许编辑,从而在Unity Editor将对象绑定到变量,被脚本控制。

[SerializeField]
Transform GameObject;

这里Transform类不止是几何变换,平移、旋转、缩放等等,SetParent。常用的属性或者函数:

  • SetParent(Transform parent, bool worldPositionStays=ture)
  • localPosition: Vector3
  • localScale:     Vector3
  • localRotation: Quaternion

Unity数学对象是预制的类,而非通用的数组或者元组:

  • 三维向量 Vector3

    • .one
    • .up .down .left .right .forward .back
  • 四元数(三维旋转) Quaternion

    • .Euler(float degx, float degy, float degz)
    • .identity
  • 时间Time

    • .deltaTime (秒)上帧到现在

Prefab预制体。Drag the GameObject from Hierarchy to Project/Assets.

Transform newGameObject = Instantiate(myPrefab);

In default render pipeline:

  • A GameObject needs a Material.
  • A Material needs a Shader.

Start using URP for rendering:

  1. Create URP from Project/Assets/Create/Rendering/Universal Render Pipeline/ Pipeline Asset (Forward Renderer) with name “xxx”. And Unity automatically create another asset called “xxx_renderer”;
  2. Project settings/Graphic section::Scriptable Render Pipeline Settings, and select “xxx(UniversalRenderPipelineAsset)”;

And in URP:

  • Create a URPAsset to use URP;
  • Create a shader for URPAsset, via Assets / Create / Shader / Universal Render Pipeline / Lit Shader Graph;
  • Create a Material using the shader above;
  • Now apply the Material to GameObject.

要用其他文件中函数或类,同目录下的,只要声明成public即可在其他地方直接用。(?存疑)

URP更快,相比于built-in render pipeline(BRP);

Check “Enable GPU Instancing” for Material.

最简单的UI,程序控制的文本显示:

using UnityEngine;
using TMPro;

public class FrameRateCounter : MonoBehaviour {

	[SerializeField]
	TextMeshProUGUI display;
}

To compute on GPU:

  1. The Compute Buffer stores data for GPU, created in scripts;

    ComputeBuffer positionsBuffer;
  2. The Compute Shader runs codes on GPU, created via Assets / Create / Shader / Compute Shader, and write kernels:

    RWStructuredBuffer _Positions;
    [numthreads(8, 8, 1)]
    void FunctionKernel (uint3 id: SV_DispatchThreadID) {}
  3. Dispatch a Compute Shader Kernel in other scripts:

    [SerializeField]
    ComputeShader computeShader;
    static readonly int positionsId = Shader.PropertyToID("_Positions");
    computeShader.SetFloat(timeId, Time.time);
    computeShader.SetBuffer(0, positionsId, positionsBuffer);
    computeShader.Dispatch(0, groups, groups, 1);
  4. Create a new Shader to fetch data computed in GPU, with BRP or URP.

如何打印Hello World?

Debug.Log is a simple command that just prints a message to Unity’s console output.

用C#script做为componet以控制GameObject的行为:

  1. GameObjects 受控于 components attached.
  2. 类名文件名必须相同 to enable scripts attached to a GameObject.
  3. Notice that in a component script of a object, the variable this refers to the attaching object. You can “clone it” in this way. The type of “this” is just the class with the same name of the file.

设置父级,以保持正确的位置变换:

public void SetParent (Transform p);

public void SetParent (Transform parent, bool worldPositionStays);

参数

parent 要使用的父变换。

worldPositionStays 如果为 true,则修改相对于父级的位置、缩放和旋转,使对象保持与之前相同的世界空间位置、旋转和缩放。

Clone a object with a C# script in Start:

Using Fractal child = Instantiate(this); to clone.

We could clone the object in an Awake method, but then the clone’s Awake method will immediately get invoked as well, which immediately creates another instance, and so on. This would keep going until Unity crashes because it’s invoking too many methods recursively, which will happen very quickly.

To avoid immediate recursion we can instead add a Start method and invoke Instantiate in there. Start is another Unity event method, which like Awake also gets invoked once after a component is created. The difference is that Start doesn’t get invoked immediately, but right before the first time an Update method would get invoked on the component, whether it has one or not. New components that get created at that point get their first update in the next frame. This means that instantiations will happen only once per frame.

2 comments

Leave a Reply