如何在人物之间建立意见系统

时间:2019-03-29 15:24:41

标签: c# unity3d

让我们说我有一个可编写脚本的对象“字符”,并为该可编写脚本的对象创建了三个字符。现在,我希望其中三个字符对其他两个字符有意见(int值)。就像角色1对角色2有30个意见,而角色1对角色2有-30个意见。

我认为简单的方法是在Characters Scriptable Object中创建两个int,但是如果我有1000个Character,我是否必须创建1000个int。关于如何创建此系统的任何想法?

1 个答案:

答案 0 :(得分:0)

在这个问题的Unity答案中,我得到了一个出色的答案。如果需要,请检查一下。

这是方法:

  1. 创建一个继承自ScriptableObject的新类
  2. 在此类中,声明一个包含意见的2D数组和一个包含您的字符的数组
  3. 创建自定义检查器以显示此网格

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[i] )
             {
                 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[i] )
             {
                 for( int j = 0 ; j < characters.Length ; ++j )
                 {
                     if( character2 == characters[j] )
                     {
                         opinions[i * characters.Length + j] = opinion;
                         return ;
                     }
                 }
                 Debug.LogError( "Character2 not found" );
             }
         }
         Debug.LogError( "Character1 not found" );
     }
 }

在名为“编辑器”的文件夹中

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; 
             }
         }
     }
 }

enter image description here

注意

如果您想进一步扩展代码,例如,字符A对字符B会有意见。但是字符B对字符A也有意见。然后在OpinionsTableEditor.cs中进行以下更改

更改此

 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 );
              }