Unity编辑脚本(启动指南)-脚本对象

在之前的编辑脚本中,我们讨论了编辑脚本的概述和重要性。我们在第1部分和第2部分中讨论了Gizmos、自定义检查器和编辑器窗口。现在,我们将给您一个关于脚本对象的洞察和概述

脚本化的对象是什么?
根据Unity:
一个类,来自于Unity的对象类,它的引用和字段可以被序列化。

 


脚本对象是什么样的
脚本对象是一种特殊类型的对象,它不需要出现在场景中,也不需要附加在一个游戏对象上,因为它可以作为项目中的资产保存。脚本对象的主要用途是以持久的方式保存数据。它只是一种单行为的数据版本,只能保存数据变量。


他们能做什么?
可以将脚本对象构建在Unity,并可以作为项目中的资产保存。它们可以在运行时保存,这意味着如果您必须在运行时或播放模式上改变一些东西,您可以使用可脚本对象来保存这些更改。您不必担心在运行时解析/序列化数据,他们会为您这样做。因为它只能存储数据,几乎和单行为一样,您不必担心它与类之间的交互。


局限性是什么?
在使用脚本时,需要记住的是脚本对象的一些限制。它们需要编辑脚本,因为它们只能在编辑器中创建。另外,您不能使用第三方工具编辑它们的外部。因此,它们只能用于保存和管理开发生命周期的数据;也就是说,它们不能被修改或保存一次。简而言之,脚本对象最适合存储游戏开发/游戏设计数据和优化数据加载。

可能的使用场景
1.你想在播放模式下调整值,并想保留它们。
2.你想要改变某些类型的游戏对象。
3.你不想改变游戏设计师或者艺术家来扰乱你的游戏对象的不相关价值。

 


在上述所有场景中,可脚本对象都是有用的,并且总是可以保存到它们自己独特的资产文件中。在游戏模式中,你可以轻松编辑脚本对象实例,让游戏设计者/艺术家迭代不用担心实际的游戏数据。此外,你的场景和前言将会更快地保存和加载。此外,它还实现了可靠的关注点分离(SoC)模式。



例子
让我们动手玩可脚本的对象。我们现在有一个简单的类 'Player.cs':

[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
public class Player : MonoBehaviour
{
     //Player data
     public string _name;
     public int _health;
     public Color _color;
 
     private MeshRenderer _renderer;
 
     void Awake()
     {
         _renderer = GetComponent<MeshRenderer>();
         _name = "John" ;
         _health = 100;
         _renderer.material.color = Color.green;
     }


我们的玩家是一个占位的立方体(为了便于理解),有名字,健康和颜色。在Awake()回调中,我们将数据分配给播放器。我们来做一个脚本对象。它只是一个简单的c#类' PlayerData ',它扩展了脚本对象:

[C#]  纯文本查看  复制代码
?
 
1
2
3
4
5
public class PlayerData : ScriptableObject
{
     public string m_name;
     public int m_health;
     public Color m_color;   
}



将可脚本对象保存为资产
为了在项目中保存我们的资产,创建一个简单的c#类,包括UnityEditor名称空间来访问编辑器函数,它不需要扩展任何类:

[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
using UnityEditor;
using UnityEngine;
 
public class MyEditorUtils
{
 
}
Now create a static generic method CreateAsset<T>() inside the class . Generic methods have type parameters and they provide a way to use types as parameter in a method:
 
public class MyEditorUtils
{
     public static void CreateAsset<T>() where T : ScriptableObject
     {
 
     }
}



在方法中添加此代码:

[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
public static void CreateAsset<T>() where T : ScriptableObject
{
      T asset = ScriptableObject.CreateInstance<T>();
 
      string path = AssetDatabase.GetAssetPath(Selection.activeObject);
      string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath(path + "/New " + typeof (T).ToString() + ".asset" );
 
      AssetDatabase.CreateAsset(asset, assetPathAndName);
      AssetDatabase.SaveAssets();
      AssetDatabase.Refresh();
      EditorUtility.FocusProjectWindow();
      Selection.activeObject = asset;
}



现在让我们逐行分解代码:

第3行:我们正在创建一个T类型的脚本对象的实例,我们正在获取我们的方法的参数。
第5、6条:我们在项目中获取所选文件夹的路径,然后为我们的资产构建路径和名称字符串。
第8行:我们正在创建一个。资产的文件和我们的资产名称和我们想要的路径。
第9行:为我们的项目节省我们的资产。
第10行:刷新和更新我们的资产视图和数据。
第11行,第12行:将项目窗口集中起来,我们的保存因此被选中。

现在让我们把它封装在一个静态方法中,这样它就可以被触发在一个[MenuItem]属性操作上,并在参数中传递PlayerData:

[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
public class MyEditorUtils
{
     [MenuItem( "Assets/Create/Create Player Data Object" )]
     public static void CreateAsset()
     {
         CreateAsset<PlayerData>();
     }
 
     public static void CreateAsset<T>() where T : ScriptableObject
     {
         T asset = ScriptableObject.CreateInstance<T>();
 
         string path = AssetDatabase.GetAssetPath(Selection.activeObject);
         string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath(path + "/New " + typeof (T).ToString() + ".asset" );
 
         AssetDatabase.CreateAsset(asset, assetPathAndName);
         AssetDatabase.SaveAssets();
         AssetDatabase.Refresh();
         EditorUtility.FocusProjectWindow();
         Selection.activeObject = asset;
     }
}




现在去看Unity编辑,看看它的作用:
 
这就是我们的PlayerData在检查器中看起来的样子:

 

[CreateAssetMenu]属性
从Unity 5.1开始,您可以使用[CreateAssetMenu]属性在一行代码中创建资产。该属性允许您在资产/创建上下文菜单中创建菜单项。这是非常快的创建资产的方法,并且不需要上面的类来做这个。你所要做的就是,用一个[CreateAssetMenu]来标记我们的PlayerData类:

[C#]  纯文本查看  复制代码
?
 
1
2
3
4
5
6
[CreateAssetMenu(fileName = "My Scriptable Object" , menuName = "My Content/Create Player Scriptable Object" , order = 0)]
public class PlayerData : ScriptableObject
{
     public string m_name;
     public int m_health;
     public Color m_color;   
}



fileName:将在资产中创建的资产文件的名称。
menuName: 在资产/创建菜单中菜单的层次结构。
order:是您的菜单项在资产/创建菜单中的顺序。我将它设置为0,显示在每个菜单的顶部。

结果如下:

 

链接和引用可脚本对象
引用和使用来自脚本对象的数据相当容易。你所要做的只是创建一个变量的PlayerData:

[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
public class Player : MonoBehaviour
{
     public PlayerData data;
     
     //Player data
     public string _name;
     public int _health;
     public Color _color;
 
     private MeshRenderer _renderer;
 
     void Awake()
     {
         _renderer = GetComponent<MeshRenderer>();
         _name = "John" ;
         _health = 100;
         _renderer.material.color = Color.green;
     }



Awake()中,将数据分配给类变量:
[C#]  纯文本查看  复制代码
?
 
1
2
3
4
5
6
void Awake()
{
      _renderer = GetComponent<MeshRenderer>();
      _name = data.m_name;
      _health = data.m_health;
      _renderer.material.color = data.m_color;
}

检视编辑器中分配引用:
 
让我们从检查器中给我们的PlayerData脚本对象提供一些值:

 

我还添加了一个标签,可以快速地在游戏视图中看到玩家的信息,在我的播放器类中获取它的引用,并在Awake()方法中更新它:

 

[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
void Awake()
{
      _renderer = GetComponent<MeshRenderer>();
      _name = data.m_name;
      _health = data.m_health;
      _renderer.material.color = data.m_color;
   
       UpdateUI();
}
 
void UpdateUI()
{
      _playerInfo.text = "Name: " + _name + "\n" + "Health: " + _health + "\n" + "Color: " + _color;
}


结果:

 

让我们再复制两个播放器数据对象,并给它们分配不同的数据:

 

取一组PlayerData并在索引上进行切换,这是我们的完整代码(用数组替换单个数据变量):

[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Player : MonoBehaviour
{
     public PlayerData data;
 
     public string _name;
     public int _health;
     public Color _color;
 
     public PlayerData[] dataArray;
 
     [Range(0, 2)]
     public int dataIndex;
 
     public Text _playerInfo;
 
     private MeshRenderer _renderer;
 
     void Update()
     {
         _renderer = GetComponent<MeshRenderer>();
         _name = dataArray[dataIndex].m_name;
         _health = dataArray[dataIndex].m_health;
         _renderer.material.color = dataArray[dataIndex].m_color;
 
         UpdateUI();
     }
 
     void UpdateUI()
     {
         _playerInfo.text = "Name: " + _name + "\n" + "Health: " + _health;
     }
}


 

这是我们最后的结果:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值