Unity 学习(三)—— 编写脚本

创建和编写脚本

Unity 支持 C#和能兼容编译 DLL的 .Net语言来编写脚本。

创建脚本

Assets -> Create -> C# Script

解析脚本文件

Unity 默认使用 VS打开 脚本文件,你也可以通过 Unity -> Preferences来选择你想要打开的编辑器。
初始文件的内容如下所示:

using UnityEngine;
using System.Collections;

public class MainPlayer : MonoBehaviour {

    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
}

脚本文件通过实现继承内置 MonoBehaviour类来完成与unity内部工作的连接。你可以认为这个类是一种实现方案,这个方案创建了一个与 GameObject相关的组件类型。每次你将脚本组件与 GameObject联系起来,它就通过实现方案产生一个物体的新实例。类的名字取自创建文件时提供的名称。类名与文件名必须一致,以确保脚本组件能与 GameObject关联。
Update 函数是你用于处理 GameObject帧更新的地方;它应该包括移动,动作触发和用户输入相应,以及在 gameplay期间需要根据时间推移来解决的任何事件。为保证 Update函数能够工作,你需要在所有游戏动作发生前构建变量、读取首选项以及和其他 GameObjects建立连接。Start 函数将会在 gameplay开始前由 Unity调用,因此你需要在这里做一些初始化。

控制 GameObject

在脚本与 GameObject相关联之前,脚本代码并不会被激活。你可以通过拖动脚本 asset到层级面板的 GamObject或到已选中的 GameObject的 Inspector上来产生关联。
关联起来后,脚本会在你按下 Play运行这个游戏是开始工作。你可以尝试下下面的开始函数:

// Use this for initialization
void Start () 
{
    Debug.Log("I am alive!");
}

你可以在 Console窗口那看到打印出来的信息。(Window -> Console)

变量和 Inspector

就像其他组件也有一些可在 Inspector中编辑一样,你也可以让你的脚本在 Inspector中编辑。

using UnityEngine;
using System.Collections;

public class MainPlayer : MonoBehaviour 
{
    public string myName;
    
    // Use this for initialization
    void Start () 
    {
        Debug.Log("I am alive and my name is " + myName);
    }
}

上面的代码在 Inspector创建了一个可编辑域“My Name”。

按下 Play,你会看到:

在 C#,你必须将变量声明为 public才能在 Inspector中看到它。

使用 Component控制 GameObject

脚本也可以通过修改 Component属性来操纵 GameObjects。它与 Inspector的区别在于:脚本可以随着时间推移来改变属性值或响应用户的输入。

访问 Component

最简单常见的情况是脚本需要访问关联到此 GameObject的其他组件。实际上,一个组件就是一个类的实例,因此,第一步就是获得你需要的 Component的引用。GetComponent 函数可以做到这个。如下所示:

void Start () 
{
    Rigidbody rb = GetComponent<Rigidbody>();
}

一旦你获得了一个 Component实例的引用,你就可以设置你想要的属性值了。

void Start () 
{
    Rigidbody rb = GetComponent<Rigidbody>();
    
    // Change the mass of the object's Rigidbody.
    rb.mass = 10f;
}

在 Inspector中有一个额外的特性可能不可用,那就是调用 Component实例的函数。

void Start ()
{
    Rigidbody rb = GetComponent<Rigidbody>();
    
    // Add a force to the Rigidbody.
    rb.AddForce(Vector3.up * 10f);
}

需要注意的是,你不能用多个定制化脚本关联一个同一个 object。如果你需要在另一个脚本中访问某个脚本,你可以使用 GetComponent且只使用这个脚本类的名字(即文件名)来指定你想要的 Component类型。
如果你尝试检索一个未添加到 GameObject上的 Component,那么 GetComponent会返回 null;所以如果你试图去改变一个 null对象的值,你会得到一个 null reference error。

访问其他 objects

虽然 objects的分开操作的,但对于脚本来说,与其他 objects保持联系也是十分常见的。比如说,一个正在跟踪的敌人需要知道玩家的位置。Unity提供了许多不同的方式来检索其他 objects,每种方式都有实用的场景。

通过变量链接 GameObject

找到相关的 GameObject的最直接的方式是为脚本添加一个 public的 GameObject变量:

public class Enemy : MonoBehaviour
{
    public GameObject player;
    
    // Other variables and functions...
}

这个变量在 Inspector是可见的:

现在你可以从场景或层级面板中拖动一个 object并分配到这个变量上。GetComponent函数和 Component访问变量对于这个 object来说是可用的,因此你可以使用下面的这段代码:

public class Enemy : MonoBehaviour {
    public GameObject player;
    
    void Start() {
        // Start the enemy ten units behind the player character.
        transform.position = player.transform.position - Vector3.forward * 10f;
    }
}

另外,如果你在脚本中声明一个 public的 Component类型的变量,你可以拖动任何一个拥有此 Component的 GameObject到这。这会直接访问这个 Component而不是 GameObject自身。

public Transform playerTransform;

寻找 child GameObjects

有时,一个游戏场景会使用大量的相同类型的 GameObjects,如敌人,导航点和障碍物。这些都需要通过一个特殊的脚本跟踪它们,这个脚本起到监督和响应它们的作用(例如,所有的导航点应该可被一个路径搜索脚本所用)。使用变量来链接这些 GameObjects是可行的,但是,如果每个导航点都要被拖到脚本的一个变量中,是十分繁琐的。同样的,如果一个导航点被删除,就必须要去移除这个变量所引用的遗失的 GameObject,这会十分麻烦。对于这种情况,尝试通过将它们变为一个 parent GameObject的 children往往是更为可行的方案。使用 parent的 Transform组件能检索到 child GameObject(因为所有的 GameObjects隐式地都会有一个 Transform组件)。

using UnityEngine;

public class WaypointManager : MonoBehaviour {
    public Transform[] waypoints;
    
    void Start() 
    {
        waypoints = new Transform[transform.childCount];
        int i = 0;
        
        foreach (Transform t in transform)
        {
            waypoints[i++] = t;
        }
    }
}
原文地址:https://www.cnblogs.com/qing2019/p/12716104.html