﻿# 03. CodeGenKit 脚本生成

在这一篇，我们学习几乎每个项目都要用到并且从中受益的功能：自动生成脚本并绑定，简称脚本生成。

## 基本使用

我们先在场景中，随便创建一些有父子结构的 GameObject，如下所示：

![image.png](https://file.liangxiegame.com/ed37997b-614b-4fb1-baa8-c23d7748c67d.png)

接着给 Player 挂上 ViewController，快捷键 （Alt + V），如下图所示：

![image.png](https://file.liangxiegame.com/cfb5f767-120f-4e0f-a69b-bdef1b6e9c98.png)


然后填写 刚刚添加的组件信息:

![image.png](https://file.liangxiegame.com/a2bc2a07-02bf-46e3-ad65-36309c290bce.png)


在这里，可以填写命名空间，要生成的脚本名，以及脚本生成的目录，当然这里也可以直接将要生成的目录拖到大方块中。

如果拖拽了目录，就会自动填写脚本生成目录，如下图所示：

![image.png](https://file.liangxiegame.com/41f2abac-2fcf-4c03-8ba0-ab45f71859f3.png)

之后，我们可以给 Player GameObject 一个子节点挂上 Bind 组件（快捷键，alt + b)，如下所示

![image.png](https://file.liangxiegame.com/e818f0e5-6bfc-436b-8f61-20fb90da4bd6.png)



Weapon 挂上的组件如下所示:
![image.png](https://file.liangxiegame.com/04e7c9a4-0bc6-4257-9793-41531c3faa64.png)


接下来我们可以点击图中的 生成代码按钮 或者是 Player 上 ViewController 的 生成代码按钮，两者点击哪个都可以。

点击之后，就会生成代码，等待编译，结果如下:

脚本目录:
![image.png](https://file.liangxiegame.com/d3fc5522-6655-4318-8bec-7f4721753110.png)

我们在看下场景中的 Player 的 Inspector 如下图所示：

![image.png](https://file.liangxiegame.com/07c51906-6c1d-49be-bb9b-faef8ce999ae.png)


我们看到，Player 自动获得了 Weapon 的引用。

而且，在 Player.cs 中可以直接访问到 Weapon，如下图所示:

![image.png](https://file.liangxiegame.com/3a9f0ac1-c05c-4cdf-b442-c33fadb6897a.png)

## 增量生成
我们再看下目录：

![image.png](https://file.liangxiegame.com/47398560-791c-4e41-8586-6b76347f2758.png)

这里有两个文件 Player 和 Player.Designer。

其中 Player 是用来给大家写逻辑用的，所以 Player 只会生成一次。

而 Player.Designer 每次点击生成代码都会重新生成。

我们看下 Player.Designer 的代码，如下:

```csharp
// Generate Id:471bf5e6-b60b-42b8-b5c8-b070a963ab4a
using UnityEngine;

// 1.请在菜单 编辑器扩展/Namespace Settings 里设置命名空间
// 2.命名空间更改后，生成代码之后，需要把逻辑代码文件（非 Designer）的命名空间手动更改
namespace QFramework.Example
{
	public partial class Player
	{

		public Transform Weapon;

	}
}
```

代码中只有一个 Weapon 。

接着，我们再给 Player 的另一个子 GameObject 挂上 Bind 脚本，如下:

![image.png](https://file.liangxiegame.com/acde8a1e-2e6f-4bee-8aa9-02cec82f2808.png)

然后点击生成代码，操作如下:

![image.png](https://file.liangxiegame.com/991db32f-8212-4d7a-8176-0065cebad93f.png)


生成之后，结果如下:

Player 多了一个 Ground Check
![image.png](https://file.liangxiegame.com/d769f7e4-1e70-4dfc-9962-27d6b99998a4.png)

再看下  Player.Designer 的代码，如下:

```csharp
// Generate Id:f512c2ed-6243-4a89-897e-bdaaabe50d63
using UnityEngine;

// 1.请在菜单 编辑器扩展/Namespace Settings 里设置命名空间
// 2.命名空间更改后，生成代码之后，需要把逻辑代码文件（非 Designer）的命名空间手动更改
namespace QFramework.Example
{
	public partial class Player
	{

		public Transform Weapon;

		public Transform GroundCheck;

	}
}
```

这次多了一个 GroundCheck。

而 Player 代码则未发生任何变化。

所以每次生成代码，Player.cs 只会生成一次，Player.Designer.cs 每次都重新生成，所以大家放心在 Player.cs 里写代码。

## 类型选择
之前我们用 Bind 绑定的 GameObject 都是 Transform 类型的，这次我们尝试绑定一下其他类型。

我们给 Weapon GameObject 挂上一个 Sprite Renderer 如下所示:

![image.png](https://file.liangxiegame.com/913a4dcb-7e35-433c-a50a-454614ddf89d.png)


然后，我们点击 Bind 的类型，显示如下：

![image.png](https://file.liangxiegame.com/9ff5d52d-61bb-43b7-b4f0-5e9c118329e1.png)

也就是说 Bind 可以选择挂在此 GameObject 上的组件。

我们选择 Sprite Render 类型，如下:

![image.png](https://file.liangxiegame.com/720ec620-1ca4-42b7-afa8-ec94ee846d06.png)

然后点击生成代码，结果如下:

![image.png](https://file.liangxiegame.com/dd6a1012-6721-4c71-9291-de008a5b8614.png)


Player 引用的  Weapon 变成了 Sprite Renderer 类型。

Player.Designer.cs 的代码变成了如下:

```csharp
// Generate Id:de59e915-d1b6-40aa-a8e5-6fc4a8bf8e3e
using UnityEngine;

// 1.请在菜单 编辑器扩展/Namespace Settings 里设置命名空间
// 2.命名空间更改后，生成代码之后，需要把逻辑代码文件（非 Designer）的命名空间手动更改
namespace QFramework.Example
{
	public partial class Player
	{

		public UnityEngine.SpriteRenderer Weapon;

		public Transform GroundCheck;

	}
}
```

Weapon 从原来的 Transform 类型变成了 SpriteRenderer 类型。

这样我们在 Player.cs 就可以拿到 SpriteRenderer 类型的 Weapon 了，如下图所示：

![image.png](https://file.liangxiegame.com/534d8275-5d63-4307-89a8-378722f0bffc.png)

## 如何设置默认的 命名空间 和 脚本生成目录
很简单，打开 QFramework 编辑器面板，（快捷键 ctrl + e 或 ctrl + shift + e)

![image.png](https://file.liangxiegame.com/4322e7cc-8f5e-4e45-abbe-d63110d2e605.png)

在 CodeGenKit 设置里就可以更改默认的命名空间和默认的脚本生成位置。

当然在这里生成了，也还是可以在 ViewController Inspector 上进行设置。

我们先改下命名空间和脚本生成路径，如下:

![image.png](https://file.liangxiegame.com/72f7df2a-40cb-443c-a1f3-f4c5d5656a4b.png)

然后我们创建一个 GameObject 挂上 ViewController 组件，结果如下:

![image.png](https://file.liangxiegame.com/f461ade5-8cf6-4bfd-a94d-c86f523cf8e8.png)

这样默认的命名空间就生效了。

## ViewController 与 ViewController 嵌套
ViewController 与 ViewController 之间可以嵌套

我们在 Player 的 Weapon GameObject 再创建一个 WeaponEffect GameObject 如下:

![image.png](https://file.liangxiegame.com/e9ef6d43-7e8c-42ff-9593-76dced914c7a.png)

然后将 WeaponEffect 挂上 Bind 脚本，如下:

![image.png](https://file.liangxiegame.com/0eed4e49-2a89-4d36-af02-4e42647cfe3a.png)

接着给 Weapon 挂一个 ViewController 脚本，如下:

![image.png](https://file.liangxiegame.com/e0b90b3b-cf9a-4688-ab6d-c73c8feb9f72.png)

我们将脚本生成目录修改一下，修改成与 Player.cs 同一个目录，如下:

![image.png](https://file.liangxiegame.com/f7c52c1e-0437-48a3-b3e1-7c9d77a080bf.png)


点击生成代码，如下所示:

![image.png](https://file.liangxiegame.com/29e139ca-9fc4-4422-9d4c-7831ad6d75c6.png)

生成完了之后，我们再将 Weapon 上的 Bind 类型改成 Weapon，如下:

![image.png](https://file.liangxiegame.com/54a25732-61ea-4dd9-84dd-7bb80d66fd2d.png)

然后点击 Bind 上的生成代码，结果如下:

![image.png](https://file.liangxiegame.com/83beb081-fb7a-48df-85f5-5caf01cac1fb.png)

这样 ViewController 与 ViewController 嵌套绑定就实现了。

在 Player.cs 中可以按照如下的方式调用 Weapon 的子 GameObject 如下:

![image.png](https://file.liangxiegame.com/c29ba2f9-39b0-436a-8084-781edaf959fe.png)

当然可以再 Weapon.cs 中写 Weapon 自己的逻辑。


## 生成 Prefab
在 ViewController 或 生成脚本的 Inspector 上，有一个生成 prefab 的选项

![image.png](https://file.liangxiegame.com/f88d06e7-2b95-47fe-ac91-c446fc550447.png)

勾选后，如下所示：

![image.png](https://file.liangxiegame.com/0b9de93d-12c9-498f-b38c-c2682aa98287.png)

这里可以修改要生成的目录，笔者选择和脚本生成的目录一致，如下:

![image.png](https://file.liangxiegame.com/7628fcb6-c9de-4fe5-9f80-8967d745b3aa.png)

然后点击，生成代码，结果如下:

场景中的 Player 变成了 prefab
![image.png](https://file.liangxiegame.com/9e71ac1b-874e-47dd-b9ab-8d64e605f8a1.png)

生成目录中也有了 prefab

![image.png](https://file.liangxiegame.com/18caef79-77b1-41a6-a102-9d53683be04d.png)

## Why？
为什么要搞一个  CodeGenKit？

因为创建脚本目录、创建脚本文件、声明成员变量或者通过 transform.Find 获取子节点的引用、然后挂脚本、拖拽赋值，这些工作量非常多，而且很繁重，如果能够把这部分工作量通过代码生成并自动赋值的方式给优化掉，那么项目的开发效率就会得到及大地提升。

CodeGenKit 中的  ViewController 除了可以用于普通的 GameObject，还可以支持 NGUI 和 UGUI 等 UI 组件。

好了，关于脚本生成的功能介绍到这里。

## 更多内容

*   转载请注明地址：[liangxiegame.com](https://liangxiegame.com) （首发） 微信公众号：凉鞋的笔记
*   QFramework 主页：[qframework.cn](https://qframework.cn)
*   QFramework 交流群: 623597263
*   QFramework Github 地址: [https://github.com/liangxiegame/qframework](https://github.com/liangxiegame/qframework)
*   QFramework Gitee 地址：[https://gitee.com/liangxiegame/QFramework](https://gitee.com/liangxiegame/QFramework)
*   GamePix 独立游戏学院 & Unity 进阶小班地址：[https://www.gamepixedu.com/](https://www.gamepixedu.com/)