创建3D阵列意见系统

时间:2019-04-03 16:57:48

标签: c# unity3d

我有两个字符'Alisha'和'John',他们之间有30的意见。但是我真正想要实现的是Alisha对john 20的看法,John对Alisha 20的看法。创建一个3D阵列来解决该问题。

我创建了两个带有意见数组的脚本对象“字符”和“ OpinionsTable”。我基本上实现了我想要的。例如,我的代码非常适合用于Characters。我还创建了一个编辑器脚本,该脚本创建了意见矩阵,但我想将其增强为3D矩阵。

Character.cs

 using UnityEngine;

 [CreateAssetMenu()]
 public class Character : ScriptableObject
 {
     public string Name;
 }

OpinionsTable.cs

using UnityEngine;

[CreateAssetMenu()]
public class OpinionsTable : ScriptableObject
{
    [SerializeField]
    private Character[] characters;

    [SerializeField]
    private int[] opinions;

    public int this[int i, int j] // Where i and j are indices of characters in the array above
    {
        get { return opinions[i * characters.Length + j]; }
        set { opinions[i * characters.Length + j] = value; }
    }
}

OpinionsTableEditor.cs

using UnityEngine;
using UnityEditor;

[CustomEditor( typeof( OpinionsTable ) )]
public class OpinionsTableEditor : Editor
{
    const float opinionsLabelWidth = 50;
    const float opinionCellSize = 25;
    SerializedProperty characters;
    SerializedProperty opinions;
    int opinionsTableWidth = 0;
    Rect opinionsTableRect;

    void OnEnable()
    {
        // Retrieve the serialized properties
        characters = serializedObject.FindProperty( "characters" );
        opinions = serializedObject.FindProperty( "opinions" );
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();

        // Check if the number of characters has been changed
        // If so, resize the opinions
        EditorGUI.BeginChangeCheck();
        EditorGUILayout.PropertyField( characters, true );
        if( EditorGUI.EndChangeCheck() )
        {
            opinions.arraySize = characters.arraySize * characters.arraySize;
        }

        // Draw opinions if there is more than one character
        if ( opinions.arraySize > 1 )
            DrawOpinions( opinions, characters );
        else
            EditorGUILayout.LabelField( "Not enough characters to draw opinions matrix" );

        serializedObject.ApplyModifiedProperties();
    }

    private void DrawOpinions( SerializedProperty opinions, SerializedProperty characters )
    {
        int charactersCount = characters.arraySize;
        if ( Event.current.type == EventType.Layout )
            opinionsTableWidth = Mathf.FloorToInt( EditorGUIUtility.currentViewWidth );

        // Get the rect of the whole matric, labels included
        Rect rect = GUILayoutUtility.GetRect(opinionsTableWidth, opinionsTableWidth, EditorStyles.inspectorDefaultMargins);

        if ( opinionsTableWidth > 0 && Event.current.type == EventType.Repaint )
            opinionsTableRect = rect;

        // Draw matrix and labels only if the rect has been computed
        if( opinionsTableRect.width > 0 )
        {
            // Compute size of opinion cell
            float cellWidth     = Mathf.Min( (opinionsTableRect.width - opinionsLabelWidth) / charactersCount, opinionCellSize );
            Rect opinionCell    = new Rect( opinionsTableRect.x + opinionsLabelWidth, opinionsTableRect.y + opinionsLabelWidth, cellWidth, cellWidth );
            Matrix4x4 guiMatrix = GUI.matrix;

            // Draw vertical labels
            for ( int i = 1 ; i <= charactersCount ; ++i )
             {
                 Rect verticalLabelRect = new Rect( opinionsTableRect.x + opinionsLabelWidth + i * opinionCell.width, opinionsTableRect.y, opinionsLabelWidth, opinionsLabelWidth );
                 Character character = characters.GetArrayElementAtIndex( i - 1 ).objectReferenceValue as Character;
                 EditorGUIUtility.RotateAroundPivot( 90f, new Vector2( verticalLabelRect.x, verticalLabelRect.y ) );
                 EditorGUI.LabelField( verticalLabelRect, character == null ? "???" : character.Name );
                 GUI.matrix = guiMatrix;
             }            

             // Draw matrix
             for ( int i = 0 ; i < charactersCount ; ++i )
             {
                 // Draw horizontal labels
                 SerializedProperty characterProperty = characters.GetArrayElementAtIndex( i );
                 Character character = characterProperty == null ? null : characters.GetArrayElementAtIndex( i ).objectReferenceValue as Character;
                 EditorGUI.LabelField( new Rect( opinionsTableRect.x, opinionCell.y, opinionsLabelWidth, opinionCell.height ), character == null ? "???" : character.Name ) ;

                 for ( int j = 0 ; j < charactersCount ; ++j )
                 {
                     opinionCell.x = opinionsTableRect.x + opinionsLabelWidth + j * cellWidth;
                     if ( j > i )
                     {
                         SerializedProperty opinion = opinions.GetArrayElementAtIndex( i * charactersCount + j );
                         opinion.intValue = EditorGUI.IntField( opinionCell, opinion.intValue );
                     }
                     else // Put grey box because the matrix is symmetrical
                     {
                         EditorGUI.DrawRect( opinionCell, Color.grey );
                     }
                 }
                 opinionCell.y += cellWidth; 
             }
        }
    }
}

我得到了正确的矩阵,还可以设置两个字符的值。

但是我要实现的两个角色之间应该有两种意见,例如a的b意见和b的a意见。如果您可以提供一种将一种意见的价值存储到另一种int的方法,那也很好。

1 个答案:

答案 0 :(得分:1)

正如我已经回答here一样,您不需要3D阵列,只需要允许编辑整个矩阵即可:

可以,但是您不需要3D阵列。您只需要允许编辑矩阵的左下角:

for ( int j = 0 ; j < charactersCount ; ++j )
{
    opinionCell.x = opinionsTableRect.x + opinionsLabelWidth + j * cellWidth;
    if ( j > i )
    {
        SerializedProperty opinion = opinions.GetArrayElementAtIndex( i * charactersCount + j );
        opinion.intValue = EditorGUI.IntField( opinionCell, opinion.intValue );
    }
    else // Put grey box because the matrix is symmetrical
    {
        EditorGUI.DrawRect( opinionCell, Color.grey );
    }
}

必须替换为

for ( int j = 0 ; j < charactersCount ; ++j )
{
    opinionCell.x = opinionsTableRect.x + opinionsLabelWidth + j * cellWidth;
    SerializedProperty opinion = opinions.GetArrayElementAtIndex( i * charactersCount + j );
    opinion.intValue = EditorGUI.IntField( opinionCell, opinion.intValue );
}