iT邦幫忙

2022 iThome 鐵人賽

DAY 28
0
Software Development

如何在Unity裡寫出具有一定擴充性的遊戲系列 第 28

Day 28:Unity簡易編輯器製作(二)—使用Odin排版ScriptableObject

  • 分享至 

  • xImage
  •  

雖然使用ScriptableObject是個很方便儲存資料的方式,不過官方預設的Inspector排版不是到非常好看,所以想趁這次機會去稍微紀錄一下Odin的Inpector排版程式,不過有些功能應該Unity也有類似的效果,可以自己找找看

在沒任何排版前,預設長這樣
https://ithelp.ithome.com.tw/upload/images/20221009/20151894f6OZbigZEy.png

程式如下
UnitData.cs

using LinXuan.TBSF.Units;
using Sirenix.OdinInspector;
using System.Collections.Generic;
using TbsFramework.Cells;
using TbsFramework.Units;
using UnityEngine;
using Sirenix.OdinInspector;

namespace LinXuan.TBSF.Data
{
    [CreateAssetMenu(fileName = "UnitData", menuName = "SaveData/UnitData")]
    [InlineEditor]
    public sealed class UnitData : ScriptableObject
    {
        [SerializeField] private string m_UnitName;


        [SerializeField] private UnitView m_UnitView;

        [SerializeField] private int m_MaxHp;
        [SerializeField] private int m_UnitNumber;
        [SerializeField] private int m_MaxStamina;
        [SerializeField] private int m_MaxMovementTimes;
        [SerializeField] private int m_MaxActionTimes;
        [SerializeField] private int m_AttackPoint;

        [SerializeField] private int m_AttackRange;
        [SerializeField] private int m_MoveRange;
        
        ...

在這邊先寫一個BoxGroup程式,此功能可以讓資料集中在同一個名稱下,程式與顯示如下

UnitData.cs

namespace LinXuan.TBSF.Data 
{ 
    [CreateAssetMenu(fileName = "UnitData", menuName = "SaveData/UnitData")] 
    public sealed class UnitData : ScriptableObject 
    { 
        [BoxGroup("Basic Info")]
        [SerializeField] private string m_UnitName; 
        [SerializeField] private int m_MaxHp; 
        [SerializeField] private int m_UnitNumber; 
        [SerializeField] private int m_MaxStamina; 
        [SerializeField] private int m_MaxMovementTimes; 
        [SerializeField] private int m_MaxActionTimes; 
        [SerializeField] private int m_AttackPoint; 
        [SerializeField] private int m_AttackRange; 
        [SerializeField] private int m_MoveRange; 
         
        [SerializeField] private UnitView m_UnitView;
        ...
    }
}

https://ithelp.ithome.com.tw/upload/images/20221009/20151894klFHHlbCP1.png

如果今天也把m_UnitNumber寫進Basic Info,Basic Info就會往下新增一列Unit Number

namespace LinXuan.TBSF.Data 
{ 
    [CreateAssetMenu(fileName = "UnitData", menuName = "SaveData/UnitData")] 
    public sealed class UnitData : ScriptableObject 
    { 
        [BoxGroup("Basic Info")]
        [SerializeField] private string m_UnitName; 
        [SerializeField] private int m_MaxHp; 
        [BoxGroup("Basic Info")]
        [SerializeField] private int m_UnitNumber;
        ...

https://ithelp.ithome.com.tw/upload/images/20221009/201518941IuBUYw9nB.png

這邊直接說跟顯示以下幾個指令的意思

[LabelWidth(70)]
固定標籤顯示的長度

[HorizonalGroup("Game Data", 75)]
應該是只會在同一個Group下的水平

[PreviewField(75)]
會留出75長度的正方形

[VerticalGroup("Game Data/States")]
同一個Group下的垂直會放在一起

[Range(5, 10)]
可以變成拖拉式的數字調整,要跟LabelWidth一起才能有效果

namespace LinXuan.TBSF.Data
{
    [CreateAssetMenu(fileName = "UnitData", menuName = "SaveData/UnitData")]
    [InlineEditor]
    public sealed class UnitData : ScriptableObject
    {
        [BoxGroup("Basic Info")]
        [SerializeField] private string m_UnitName;
        [HorizontalGroup("GameDataGroup")]
        [PreviewField(75)]
        [SerializeField] private UnitView m_UnitView;
        [VerticalGroup("GameDataGroup/States")]
        [SerializeField] private int m_MaxHp;
        [VerticalGroup("GameDataGroup/States")]
        [SerializeField] private int m_UnitNumber;
        [VerticalGroup("GameDataGroup/States")]
        [SerializeField] private int m_MaxStamina;
        [VerticalGroup("GameDataGroup/States")]
        [SerializeField] private int m_MaxMovementTimes;
        [VerticalGroup("GameDataGroup/States")]
        [SerializeField] private int m_MaxActionTimes;
        [VerticalGroup("GameDataGroup/States")]
        [SerializeField] private int m_AttackPoint;
        [VerticalGroup("GameDataGroup/States")]
        [LabelWidth(70)]
        [Range(0, 10)]
        [SerializeField] private int m_AttackRange;
        [VerticalGroup("GameDataGroup/States")]
        [SerializeField] private int m_MoveRange;

https://ithelp.ithome.com.tw/upload/images/20221009/20151894WOrJfrVTSw.png

[HideLabel] 隱藏會顯示在Inspector上的文字,像這邊隱藏UnitView後左側就不會看到UnitView的字

[HorizontalGroup("GameDataGroup")] 
[PreviewField(75)] 
[HideLabel] 
[SerializeField] private UnitView m_UnitView;

https://ithelp.ithome.com.tw/upload/images/20221009/20151894wqN7JLQdvz.png

[InlineEditor] 只要加入這段程式,就可以顯示ScriptableObject的資料在Inspector上

[InlineEditor] 
public sealed class UnitData : ScriptableObject 
{
    ...

https://ithelp.ithome.com.tw/upload/images/20221009/201518945b8Y1DsGgT.png

參考資料

How to Use Odin Inspector with Scriptable Objects
流離之歌


上一篇
Day 27:Unity簡易編輯器製作(一)—使用Odin製作單位編輯面板
下一篇
Day 29:還可以更好
系列文
如何在Unity裡寫出具有一定擴充性的遊戲30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言