Here is how I would do it:
- Create a new class inheriting from ScriptableObject
- In this class, declare a 2D array containing the opinions, and an array containing your characters
- Make a custom inspector to display this grid
EDIT : Because I have already faced you problem in the past, but never took the time to implement a solution, I decided to give it a try. However, you will have to make some changes to fit your Character class.
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 GetOpinion( Character character1, Character character2 )
{
for( int i = 0 ; i < characters.Length ; ++i )
{
if( character1 == characters *)*
{
for( int j = 0 ; j < characters.Length ; ++j )
{
if( character2 == characters[j] )
return opinions[i * characters.Length + j];;
}
Debug.LogError( “Character2 not found” );
}
}
Debug.LogError( “Character1 not found” );
return -1;
}
public void SetOpinion( Character character1, Character character2, int opinion )
{
for( int i = 0 ; i < characters.Length ; ++i )
{
if( character1 == characters )
{
for( int j = 0 ; j < characters.Length ; ++j )
{
if( character2 == characters[j] )
{
opinions[i * characters.Length + j] = opinion;
// Remove the following line if Opinion( A, B ) must be different from Opinion( B, A )
opinions[j * characters.Length + i] = opinion;
return ;
}
}
Debug.LogError( “Character2 not found” );
}
}
Debug.LogError( “Character1 not found” );
}
}
----
## OpinionsTableEditor.cs
>> IN A FOLDER CALLED EDITOR <<
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 );
}
// Remove following else if Opinion( A, B ) must be different from Opinion( B, A )
else
{
// Put grey box because the matrix is symmetrical
EditorGUI.DrawRect( opinionCell, Color.grey );
}
}
opinionCell.y += cellWidth;
}
}
}
}
## Result
[135558-opinionstable.png|135558]_
_