#c# #unity3d
#c# #unity3d
Вопрос:
Допустим, у меня есть скриптовый объект ‘Characters’, и я создаю три символа этого скриптового объекта. Теперь я хочу, чтобы у трех символов было мнение (значение int) о двух других символах. Например, символ 1 имеет 30 мнений о символе 2, а символ 1 имеет -30 мнений о символе 2.
Я думаю, что самый простой способ — создать два целых числа в объекте Characters Scriptable, но если бы у меня было 1000 символов, должен ли я создавать 1000 целых чисел? Есть идеи о том, как создать эту систему?
Комментарии:
1. Вам нужен контейнер, в этом случае может подойти словарь, поэтому словарь, который связывает ‘Character’ с целым. Например, Character1.opinions(character2) и значением будет ваш рейтинг мнений. Затем вам просто нужен сценарий запуска для динамического заполнения этих словарей для каждого символа в начале
2. Мне 14 лет, и я не совсем новичок в UNITY. Можете ли вы показать мне код для этого?
3. tutorialsteacher.com/csharp/csharp-dictionary может быть, это хорошее место для начала.
4. Если у вас 1000 символов, то вам придется хранить
n * (n - 1) = 999000
мнения, гдеn
— количество символов. Т.е. у каждого символа (n
) есть мнение для всех остальных (n - 1
) символов.5. Могу ли я задать любой объект в словаре. Как класс символов. Что-то вроде IDictionary<Символ, int> dict = новый словарь<символ, int>();
Ответ №1:
Я только что получил блестящий ответ в Unity Answers на этот вопрос. Проверьте это, если хотите.
Вот как это сделать:
- Создайте новый класс, наследующий от ScriptableObject
- В этом классе объявите 2D-массив, содержащий мнения, и массив, содержащий ваши символы
- Создайте пользовательский инспектор для отображения этой сетки
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" );
}
}
В папке под названием ‘Editor’
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 amp;amp; 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. Затем внесите следующие изменения в 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 );
}