Создайте систему 3D-мнений - PullRequest
0 голосов
/ 03 апреля 2019

У меня есть два персонажа «Алиша» и «Джон», которые имеют мнение между ними 30. Но чего я действительно хочу достичь, так это того, что у Алиши есть мнение о Джоне 20, а у Джона есть Мнение об Алише 20. Короче говоря,создайте 3D-массив для решения этой проблемы.

Я создал два объекта Scriptable - 'Character' и 'OpinionsTable' с массивом мнений.В основном я достиг того, чего хочу.Мой код отлично работает для символов, как, например.Я также создал сценарий редактора, создающий матрицу мнений, но я хочу улучшить его до 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 Ответ

1 голос
/ 03 апреля 2019

Как я уже ответил здесь , вам не нужен трехмерный массив, вам просто нужно разрешить редактирование всей матрицы:

Конечно, но вы этого не делаетенужен 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 );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...