Jump to content

How to get complex structures in properties?


photo

Recommended Posts

Posted

Здравствуйте! Как мне правильно скопировать сложную структуру из свойств в созданную структуру в скрипте? Что-то мозг совсем отказывается работать, выручайте пожалуйста! :)
P.S. XML вообще не знаю, если что то не так делаю, подскажите пожалуйста.
Спасибо!

FootstepCollections.prop FootstepsSystem.cs

Posted

Здравствуйте, @Snake-Eyes

Не совсем понятно, для чего Вам писать .prop - файл на xml вручную и работать с ним из компонента...

Обычной практикой здесь было бы просто определить нужную структурку в C#-компоненте, добавить соответствующий параметр и затем его использовать (в конечном итоге "под капотом" при компиляции компонента соответствующий prop-файл будет автоматически сгенерирован). Затем просто накинуть компонент на ноду, указать нужное количество файлов, масок и.т.п. И дергать из кода нужные Вам элементы массива структур.

using System.Collections;
using System.Collections.Generic;
using Unigine;

[Component(PropertyGuid = "GUID_вашего_компонента")]
public class FootstepsSystem : Component
{
	[ShowInEditor] 
	private SoundSource soundSource;
	
	//...

	private ShapeCapsule shape;
	private LandscapeFetch landscapeFetch = new();

	// объявляем структуру
	public struct FootstepsData
	{
		public int[] LayerMapMasks;
		public List<AssetLink> FootstepSounds;
		public AssetLink JumpSound;
		public AssetLink LandSound;
	}
  
	// Параметр, представляющий собой массив определенных выше структур 
	[ShowInEditor]
	private List<FootstepsData> footstepDatas = null;

	void Init()
	{
		//...

		// создаем SoundSource, используя файл шагов с нужным индексом
		soundSource = new SoundSource(footstepDatas[0].FootstepSounds[0].Path);

        // ...
      
		// можно поменять звуковой файл, который будет проигрываться (например, прыжок)
		soundSource.SampleName = footstepDatas[0].JumpSound.Path;

        // ...
	}

	void Update()
	{

	}
}

Еще момент: вместо string-полей для путей до файлов ваших ассетов удобнее пользоваться типом AssetLink, по сути получится то же самое, только в редакторе вместо того, чтобы прописывать путь вручную при настройке, можно будет просто дропнуть в поле ассет. В коде у параметра AssetLink просто берете Path и получаете свой путь. 

Вот так это будет выглядеть в редакторе:

image.png

Надеюсь, это поможет!

Если я неверно понял задачу, объясните пожалуйста, что именно Вы хотите сделать.

Спасибо!

 

Posted
37 minutes ago, fox said:

Не совсем понятно, для чего Вам писать .prop - файл на xml вручную и работать с ним из компонента...

Дело в том что мне нужно где-то хранить заполненные данные, и когда нужно просто их откуда-то "тянуть". Тут есть несколько вариантов, либо делать node reference вешать компонент и в этом компоненте хранить данные. 2 способ Json но он явно не для этого... 3. Props'ы, я так понял они работают как аналог SciptableObject(SO) в юнити? (грубо говоря). В общем нужен подход что бы не заполнять данные по сто раз(в случае чего), а где то их хранить. К примеру давайте представим что у меня есть 16 звуков шагов, которые работают на определенной маске. Понятно что если допустим сделать лист, и как - то переименовать то все заполненные данные просто сбросятся, и нужно заново это 16 дорожек заполнять. Я прикреплю 3 скрипта когда "игрался" с landscapeFetch. В общем исходя из этого я сделал вывод что надо что-то типо SO как в юнити для удобства. Может быть я ошибаюсь и есть более "гибкие" решения в Unigine? 

LandscapeIntersection.cs Footsteps.cs FootstepsData.cs

Posted

На самом деле, если хочется хранить где-то данные в файлах и "тянуть", то можно использовать и Json , и Xml классы, собственно для этого они и предназначены, и используются внутри движком  для парсинга файлов проперти и графов материалов, например. Можно вообще хранить данные в текстовых или бинарных файлах и парсить потом вручную как угодно.

Примеры использования классов можно найти в документации в статьях раздела API или в сэмплах SDK:

Если прямо хочется "тянуть" из проперти в компонент - тоже можно!

Вот, к примеру, настроенное проперти для Вашей структурки из примера

<?xml version="1.0" encoding="utf-8"?>
<property version="2.19.0.1" name="steps_prop" manual="1" editable="1">
	<!--Объявление структурки-->
	<struct name="FootstepsData">
		<parameter name="LayerMapMasks" type="array" array_type="int"/>
		<parameter name="FootstepSounds" type="array" array_type="file"/>
		<parameter name="JumpSound" type="file"/>
		<parameter name="LandSound" type="file"/>
	</struct>
	<parameter name="soundSource" type="node" filter="SoundSource"/>
	<!--Параметр-Массив, откуда будем брать данные-->
	<parameter name="footstepDatas" type="array" array_type="FootstepsData">
		<value>
			<parameter name="LayerMapMasks" type="array" array_type="int">
				<value>1</value>
				<value>2</value>
			</parameter>
			<parameter name="FootstepSounds" type="array" array_type="file">
				<value>step1.ogg</value>
				<value>step2.ogg</value>
			</parameter>
			<parameter name="JumpSound" type="file">jump.ogg</parameter>
			<parameter name="LandSound" type="file">land.ogg</parameter>
		</value>
		<value>
			<parameter name="LayerMapMasks" type="array" array_type="int">
				<value>1</value>
				<value>2</value>
				<value>3</value>
			</parameter>
			<parameter name="FootstepSounds" type="array" array_type="file">
				<value>concrete.ogg</value>
				<value>grass.ogg</value>
				<value>snow.ogg</value>
			</parameter>
			<parameter name="JumpSound" type="file">jump.ogg</parameter>
			<parameter name="LandSound" type="file">land.ogg</parameter>
		</value>
	</parameter>
</property>

А вот пример кода компонента с методом, который заберет данные из проперти и положит в Ваш массив структур (код без проверок, просто в качестве быстрой иллюстрации).

public class FootstepsSystem : Component
{
	// ...
	[ShowInEditor]
	private Property DataStorage=null;	// <-- сюда можно накинуть нужное преднастроенное проперти в редакторе, 
  										// либо просто из кода загрузить (как удобнее)

	// объявляем структуру, соответствующую структуре в проперти
	private struct FootstepsData
	{
		public int[] LayerMapMasks;
		public List<AssetLink> FootstepSounds;
		public AssetLink JumpSound;
		public AssetLink LandSound;
	}
	// массив определенных выше структур, в который будем "тянуть"
	private List<FootstepsData> footstepDatas = new List<FootstepsData>();

	// пример метода, "тянущего" данные массива структур из соответствующего параметра проперти
	// и заполняющего массив, который мы будем использовать
	private List<FootstepsData> getFootstepData(PropertyParameter fsd_param)
	{
	  // инициализируем массив для использования в приложении и перебираем все элементы параметра проперти
	  List<FootstepsData> footstepData = new List<FootstepsData>();
	  for (int i = 0; i < fsd_param.ArraySize; i++)
	  {
		 FootstepsData fsd = new FootstepsData();
		 // берем элемент списка
		 PropertyParameter elem = fsd_param.GetChild(i);
 
		 // берем первого потомка (маски) по индексу, 
		 // а можно по имени искать (как в prop-файле объявлено), через fsd_param.FindChild("LayerMapMasks")
		 PropertyParameter masks = elem.GetChild(0);

		 // "тянем" все маски, что есть в этом элементе
		 fsd.LayerMapMasks = new int[masks.ArraySize];
		 for (int j=0; j < masks.ArraySize; j++)
		 {
			fsd.LayerMapMasks[j] = masks.GetChild(j).ValueInt;
		 }
			
		 // берем второго потомка (sound-файлы) по индексу
		 PropertyParameter sound_files = elem.GetChild(1);
		 // "тянем" весь список звуковых файлов, что есть в этом элементе
		 fsd.FootstepSounds = new List<AssetLink>();
		 for (int j=0; j < sound_files.ArraySize; j++)
		 {
		    fsd.FootstepSounds.Add(new AssetLink(sound_files.GetChild(j).ValueFile));
		 }
		 // "забираем" так же по индексу звуковые файлы для прыжка и приземления 
		 fsd.JumpSound = new AssetLink(elem.GetChild(2).ValueFile);
		 fsd.LandSound = new AssetLink(elem.GetChild(3).ValueFile);
		 // добавляем заполненный элемент в наш массив, который используем в приложении
		 footstepData.Add(fsd);
	  }
	  return footstepData;
	}
  
  // ...
  
  
  void Init()
  {
	  // берем у проперти рутовый параметр
	  PropertyParameter root_parameter = DataStorage.ParameterPtr;

	  // берем параметр с нужным нам массивом структур и "тянем" все, что нам надо	
	  footstepDatas = getFootstepData(root_parameter.GetChild(root_parameter.FindChild("footstepDatas")));

	  // смотрим, что получилось
	  foreach( FootstepsData elem in footstepDatas)
	  {
			Log.Message("-- MASKS: \n");
			foreach( int mask in elem.LayerMapMasks)
				Log.Message("----: {0} \n", mask);
			Log.Message("-- SOUNDS: \n");
			foreach( AssetLink sfile in elem.FootstepSounds)
				Log.Message("----: {0} \n", sfile.Path);
			Log.Message("-- JumpSound: {0} \n", elem.JumpSound.Path);
			Log.Message("-- LandSound: {0} \n", elem.LandSound.Path);
	  }
	  //...

  }
   // ...
}

Надеюсь, это поможет!

Спасибо!

  • Thanks 1
Posted (edited)

Спасибо большое!

P.S. Есть предложение по редактору для будущих версий движка: Вот к примеру есть коллекция в скрипте. Было бы прикольно если мы брали пачку файлов одного типа и сразу дропали в поле, а не заполняли по одному (надеюсь поймете).

Edited by Snake-Eyes
×
×
  • Create New...