initial upload
This commit is contained in:
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b390e5b7c8d51a44fa4f560d93e8067f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using Convai.Scripts.Runtime.LoggerSystem;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Convai.Scripts.Runtime.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// Data class for Section Change Events
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class SectionChangeEventsData
|
||||
{
|
||||
[SerializeField] public string id;
|
||||
[SerializeField] public UnityEvent onSectionStart;
|
||||
[SerializeField] public UnityEvent onSectionEnd;
|
||||
private NarrativeDesignManager _manager;
|
||||
|
||||
private string SectionName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_manager == null) return string.Empty;
|
||||
SectionData sectionData = _manager.sectionDataList.Find(s => s.sectionId == id);
|
||||
return sectionData?.sectionName ?? "Unknown Section";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the Section Change Events
|
||||
/// </summary>
|
||||
/// <param name="manager"> The Narrative Design Manager </param>
|
||||
public void Initialize(NarrativeDesignManager manager)
|
||||
{
|
||||
_manager = manager;
|
||||
|
||||
onSectionStart.RemoveListener(LogSectionStart);
|
||||
onSectionStart.AddListener(LogSectionStart);
|
||||
|
||||
onSectionEnd.RemoveListener(LogSectionEnd);
|
||||
onSectionEnd.AddListener(LogSectionEnd);
|
||||
}
|
||||
|
||||
private void LogSectionStart()
|
||||
{
|
||||
ConvaiLogger.DebugLog($"Section {SectionName} started", ConvaiLogger.LogCategory.Character);
|
||||
}
|
||||
|
||||
private void LogSectionEnd()
|
||||
{
|
||||
ConvaiLogger.DebugLog($"Section {SectionName} ended", ConvaiLogger.LogCategory.Character);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32b4f9b2242945c19917f76c7ceb0a71
|
||||
timeCreated: 1707390195
|
||||
@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using Convai.Scripts.Runtime.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Convai.Scripts.Runtime.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// Data class for Section Data
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class SectionData
|
||||
{
|
||||
[JsonProperty("section_id")] [ReadOnly] [SerializeField]
|
||||
public string sectionId;
|
||||
|
||||
[JsonProperty("section_name")] [ReadOnly] [SerializeField]
|
||||
public string sectionName;
|
||||
|
||||
[JsonProperty("bt_constants")] [HideInInspector] [SerializeField]
|
||||
public string behaviorTreeConstants;
|
||||
|
||||
[JsonProperty("objective")] [ReadOnly] [SerializeField]
|
||||
public string objective;
|
||||
|
||||
[JsonProperty("character_id")] [ReadOnly] [HideInInspector] [SerializeField]
|
||||
public string characterId;
|
||||
|
||||
[JsonProperty("decisions")] [ReadOnly] public object Decisions;
|
||||
|
||||
[JsonProperty("parents")] [ReadOnly] public object Parents;
|
||||
|
||||
[JsonProperty("triggers")] [ReadOnly] public object Triggers;
|
||||
|
||||
[JsonProperty("updated_character_data")] [ReadOnly]
|
||||
public object UpdatedCharacterData;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98ee0e1dea8bb8c4ba9fe2daf30e9960
|
||||
timeCreated: 1706764030
|
||||
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using Convai.Scripts.Runtime.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Convai.Scripts.Runtime.Features
|
||||
{
|
||||
[Serializable]
|
||||
public class TriggerData
|
||||
{
|
||||
[JsonProperty("trigger_id")] [ReadOnly] [SerializeField]
|
||||
public string triggerId;
|
||||
|
||||
[JsonProperty("trigger_name")] [ReadOnly] [SerializeField]
|
||||
public string triggerName;
|
||||
|
||||
[JsonProperty("trigger_message")] [ReadOnly] [SerializeField]
|
||||
public string triggerMessage;
|
||||
|
||||
[JsonProperty("destination_section")] [ReadOnly] [SerializeField]
|
||||
public string destinationSection;
|
||||
|
||||
[JsonProperty("character_id")] [HideInInspector] [SerializeField]
|
||||
public string characterId;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed95a107485d00746a551222f53d0950
|
||||
timeCreated: 1706764014
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ecfb3b2eea944946a1d2336205b5eaad
|
||||
timeCreated: 1706853590
|
||||
@ -0,0 +1,151 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Convai.Scripts.Runtime.LoggerSystem;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Convai.Scripts.Runtime.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// API client for the Narrative Design API.
|
||||
/// </summary>
|
||||
public class NarrativeDesignAPI
|
||||
{
|
||||
private const string BASE_URL = "https://api.convai.com/character/narrative/";
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NarrativeDesignAPI" /> class.
|
||||
/// </summary>
|
||||
public NarrativeDesignAPI()
|
||||
{
|
||||
_httpClient = new HttpClient
|
||||
{
|
||||
// Set a default request timeout if needed
|
||||
Timeout = TimeSpan.FromSeconds(30) // Example: 30 seconds
|
||||
};
|
||||
|
||||
// Get the API key from the ConvaiAPIKeySetup object
|
||||
if (ConvaiAPIKeySetup.GetAPIKey(out string apiKey))
|
||||
{
|
||||
// Set default request headers here
|
||||
_httpClient.DefaultRequestHeaders.Add("CONVAI-API-KEY", apiKey);
|
||||
|
||||
// Set default headers like Accept to expect a JSON response
|
||||
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> CreateSectionAsync(string characterId, string objective, string sectionName, string behaviorTreeCode = null, string btConstants = null)
|
||||
{
|
||||
string endpoint = "create-section";
|
||||
HttpContent content = CreateHttpContent(new Dictionary<string, object>
|
||||
{
|
||||
{ "character_id", characterId },
|
||||
{ "objective", objective },
|
||||
{ "section_name", sectionName },
|
||||
{ "behavior_tree_code", behaviorTreeCode },
|
||||
{ "bt_constants", btConstants }
|
||||
});
|
||||
return await SendPostRequestAsync(endpoint, content);
|
||||
}
|
||||
|
||||
public async Task<string> GetSectionAsync(string characterId, string sectionId)
|
||||
{
|
||||
string endpoint = "get-section";
|
||||
HttpContent content = CreateHttpContent(new Dictionary<string, object>
|
||||
{
|
||||
{ "character_id", characterId },
|
||||
{ "section_id", sectionId }
|
||||
});
|
||||
return await SendPostRequestAsync(endpoint, content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of sections for a character.
|
||||
/// </summary>
|
||||
/// <param name="characterId"> The character ID. </param>
|
||||
/// <returns> A JSON string containing the list of sections. </returns>
|
||||
public async Task<string> ListSectionsAsync(string characterId)
|
||||
{
|
||||
string endpoint = "list-sections";
|
||||
HttpContent content = CreateHttpContent(new Dictionary<string, object>
|
||||
{
|
||||
{ "character_id", characterId }
|
||||
});
|
||||
return await SendPostRequestAsync(endpoint, content);
|
||||
}
|
||||
|
||||
public async Task<string> CreateTriggerAsync(string characterId, string triggerName, string triggerMessage = null, string destinationSection = null)
|
||||
{
|
||||
string endpoint = "create-trigger";
|
||||
|
||||
HttpContent content = CreateHttpContent(new Dictionary<string, object>
|
||||
{
|
||||
{ "character_id", characterId },
|
||||
{ "trigger_message", triggerMessage },
|
||||
{ "destination_section", destinationSection }
|
||||
});
|
||||
|
||||
return await SendPostRequestAsync(endpoint, content);
|
||||
}
|
||||
|
||||
public async Task<string> GetTriggerAsync(string characterId, string triggerId)
|
||||
{
|
||||
string endpoint = "get-trigger";
|
||||
HttpContent content = CreateHttpContent(new Dictionary<string, object>
|
||||
{
|
||||
{ "character_id", characterId },
|
||||
{ "trigger_id", triggerId }
|
||||
});
|
||||
return await SendPostRequestAsync(endpoint, content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of triggers for a character.
|
||||
/// </summary>
|
||||
/// <param name="characterId"> The character ID. </param>
|
||||
/// <returns> A JSON string containing the list of triggers. </returns>
|
||||
public async Task<string> GetTriggerListAsync(string characterId)
|
||||
{
|
||||
string endpoint = "list-triggers";
|
||||
HttpContent content = CreateHttpContent(new Dictionary<string, object>
|
||||
{
|
||||
{ "character_id", characterId }
|
||||
});
|
||||
return await SendPostRequestAsync(endpoint, content);
|
||||
}
|
||||
|
||||
private static HttpContent CreateHttpContent(Dictionary<string, object> data)
|
||||
{
|
||||
//Dictionary where all values are not null
|
||||
Dictionary<string, object> dataToSend =
|
||||
data.Where(keyValuePair => keyValuePair.Value != null).ToDictionary(keyValuePair => keyValuePair.Key, keyValuePair => keyValuePair.Value);
|
||||
|
||||
// Serialize the dictionary to JSON
|
||||
string json = JsonConvert.SerializeObject(dataToSend);
|
||||
|
||||
// Convert JSON to HttpContent
|
||||
return new StringContent(json, Encoding.UTF8, "application/json");
|
||||
}
|
||||
|
||||
private async Task<string> SendPostRequestAsync(string endpoint, HttpContent content)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpResponseMessage response = await _httpClient.PostAsync(BASE_URL + endpoint, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
ConvaiLogger.Exception($"Request to {endpoint} failed: {e.Message}", ConvaiLogger.LogCategory.GRPC);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13850aaec3d742c2867a15ab2273a1e0
|
||||
timeCreated: 1706546525
|
||||
@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Convai.Scripts.Runtime.Features
|
||||
{
|
||||
public class NarrativeDesignKeyController : MonoBehaviour
|
||||
{
|
||||
public List<NarrativeDesignKey> narrativeDesignKeys;
|
||||
|
||||
[Serializable]
|
||||
public class NarrativeDesignKey
|
||||
{
|
||||
public string name;
|
||||
public string value;
|
||||
}
|
||||
|
||||
public void SetTemplateKey(Dictionary<string, string> keyValuePairs)
|
||||
{
|
||||
narrativeDesignKeys.Clear();
|
||||
narrativeDesignKeys.AddRange(from item in keyValuePairs
|
||||
select new NarrativeDesignKey { name = item.Key, value = item.Value });
|
||||
}
|
||||
public void AddTemplateKey(string name, string value)
|
||||
{
|
||||
narrativeDesignKeys.Add(new NarrativeDesignKey { name = name, value = value });
|
||||
}
|
||||
public void RemoveTemplateKey(string name)
|
||||
{
|
||||
NarrativeDesignKey reference = narrativeDesignKeys.Find(x => x.name == name);
|
||||
if(reference == null) return;
|
||||
narrativeDesignKeys.Remove(reference);
|
||||
}
|
||||
public void UpdateTemplateKey(string name, string value)
|
||||
{
|
||||
NarrativeDesignKey reference = narrativeDesignKeys.Find(x => x.name == name);
|
||||
if (reference == null) return;
|
||||
reference.value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d526d030017744949b7412a85e6134d3
|
||||
timeCreated: 1725884181
|
||||
@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Convai.Scripts.Runtime.Core;
|
||||
using Convai.Scripts.Runtime.LoggerSystem;
|
||||
using Newtonsoft.Json;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Convai.Scripts.Runtime.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages the narrative design for a ConvaiNPC.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(ConvaiNPC))]
|
||||
public class NarrativeDesignManager : MonoBehaviour
|
||||
{
|
||||
public List<SectionChangeEventsData> sectionChangeEventsDataList = new();
|
||||
public List<SectionData> sectionDataList = new();
|
||||
public List<TriggerData> triggerDataList = new();
|
||||
private ConvaiNPC _convaiNpc;
|
||||
private string _currentSectionID;
|
||||
private NarrativeDesignAPI _narrativeDesignAPI;
|
||||
|
||||
private NarrativeDesignAPI NarrativeDesignAPI => _narrativeDesignAPI ??= new NarrativeDesignAPI();
|
||||
private ConvaiNPC ConvaiNpc => _convaiNpc ??= GetComponent<ConvaiNPC>();
|
||||
private string CharacterID => ConvaiNpc.characterID;
|
||||
|
||||
private async void Awake()
|
||||
{
|
||||
_convaiNpc = GetComponent<ConvaiNPC>();
|
||||
await Task.WhenAll(UpdateSectionListAsync(), UpdateTriggerListAsync());
|
||||
}
|
||||
|
||||
private async void Reset()
|
||||
{
|
||||
await Task.WhenAll(UpdateSectionListAsync(), UpdateTriggerListAsync());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the section list from the server.
|
||||
/// </summary>
|
||||
public async Task UpdateSectionListAsync()
|
||||
{
|
||||
List<SectionData> updatedSectionList = await GetSectionListFromServerAsync();
|
||||
UpdateSectionDataList(updatedSectionList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the trigger list from the server.
|
||||
/// </summary>
|
||||
public async Task UpdateTriggerListAsync()
|
||||
{
|
||||
await ListTriggersAsync(CharacterID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the section event list changes.
|
||||
/// </summary>
|
||||
public void OnSectionEventListChange()
|
||||
{
|
||||
foreach (SectionChangeEventsData sectionChangeEventsData in sectionChangeEventsDataList) sectionChangeEventsData.Initialize(this);
|
||||
}
|
||||
|
||||
private async Task<List<SectionData>> GetSectionListFromServerAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
string sections = await NarrativeDesignAPI.ListSectionsAsync(CharacterID);
|
||||
return JsonConvert.DeserializeObject<List<SectionData>>(sections);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ConvaiLogger.Error($"Please setup API Key properly. FormatException occurred: {e.Message}", ConvaiLogger.LogCategory.Character);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public event Action OnTriggersUpdated;
|
||||
|
||||
private async Task ListTriggersAsync(string characterId)
|
||||
{
|
||||
try
|
||||
{
|
||||
string triggers = await NarrativeDesignAPI.GetTriggerListAsync(characterId);
|
||||
triggerDataList = JsonConvert.DeserializeObject<List<TriggerData>>(triggers);
|
||||
OnTriggersUpdated?.Invoke();
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
ConvaiLogger.Exception($"Format Exception occurred: {e.Message}", ConvaiLogger.LogCategory.Character);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Updates the current section.
|
||||
/// </summary>
|
||||
/// <param name="sectionID"> The section ID to update to. </param>
|
||||
public void UpdateCurrentSection(string sectionID)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_currentSectionID))
|
||||
{
|
||||
_currentSectionID = sectionID;
|
||||
InvokeSectionEvent(_currentSectionID, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentSectionID.Equals(sectionID))
|
||||
return;
|
||||
|
||||
InvokeSectionEvent(_currentSectionID, false);
|
||||
_currentSectionID = sectionID;
|
||||
InvokeSectionEvent(_currentSectionID, true);
|
||||
}
|
||||
|
||||
private void InvokeSectionEvent(string id, bool isStarting)
|
||||
{
|
||||
SectionChangeEventsData sectionChangeEventsData = sectionChangeEventsDataList.Find(x => x.id == id);
|
||||
|
||||
if (sectionChangeEventsData == null)
|
||||
{
|
||||
ConvaiLogger.Info($"No Section Change Events have been created for sectionID: {id}", ConvaiLogger.LogCategory.Actions);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isStarting)
|
||||
sectionChangeEventsData.onSectionStart?.Invoke();
|
||||
else
|
||||
sectionChangeEventsData.onSectionEnd?.Invoke();
|
||||
}
|
||||
|
||||
private void UpdateSectionDataList(List<SectionData> updatedSectionList)
|
||||
{
|
||||
Dictionary<string, SectionData> updatedSectionDictionary = updatedSectionList.ToDictionary(s => s.sectionId);
|
||||
|
||||
// Remove sections that no longer exist
|
||||
sectionDataList.RemoveAll(currentSection => !updatedSectionDictionary.ContainsKey(currentSection.sectionId));
|
||||
|
||||
foreach (SectionData currentSection in sectionDataList.ToList())
|
||||
if (updatedSectionDictionary.TryGetValue(currentSection.sectionId, out SectionData updatedSection))
|
||||
{
|
||||
currentSection.sectionName = updatedSection.sectionName;
|
||||
currentSection.objective = updatedSection.objective;
|
||||
updatedSectionDictionary.Remove(currentSection.sectionId);
|
||||
}
|
||||
|
||||
foreach (SectionData newSection in updatedSectionDictionary.Values) sectionDataList.Add(newSection);
|
||||
|
||||
foreach (SectionChangeEventsData sectionChangeEvent in sectionChangeEventsDataList) sectionChangeEvent.Initialize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d56bc33052944e0aba5a0fe7073c3ab
|
||||
timeCreated: 1706546743
|
||||
@ -0,0 +1,77 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Convai.Scripts.Runtime.Core;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Convai.Scripts.Runtime.Features
|
||||
{
|
||||
public class NarrativeDesignTrigger : MonoBehaviour
|
||||
{
|
||||
public ConvaiNPC convaiNPC;
|
||||
[HideInInspector] public int selectedTriggerIndex;
|
||||
[HideInInspector] public List<string> availableTriggers = new();
|
||||
public UnityEvent onTriggerEvent;
|
||||
|
||||
private NarrativeDesignManager _narrativeDesignManager;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
UpdateNarrativeDesignManager();
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (other.gameObject.CompareTag("Player")) InvokeSelectedTrigger();
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
UpdateNarrativeDesignManager();
|
||||
}
|
||||
|
||||
private void UpdateNarrativeDesignManager()
|
||||
{
|
||||
if (convaiNPC != null)
|
||||
{
|
||||
_narrativeDesignManager = convaiNPC.GetComponent<NarrativeDesignManager>();
|
||||
if (_narrativeDesignManager != null) UpdateAvailableTriggers();
|
||||
}
|
||||
else
|
||||
{
|
||||
availableTriggers.Clear();
|
||||
selectedTriggerIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateAvailableTriggers()
|
||||
{
|
||||
if (_narrativeDesignManager != null)
|
||||
{
|
||||
availableTriggers = _narrativeDesignManager.triggerDataList.Select(trigger => trigger.triggerName).ToList();
|
||||
if (selectedTriggerIndex >= availableTriggers.Count) selectedTriggerIndex = availableTriggers.Count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public void InvokeSelectedTrigger()
|
||||
{
|
||||
if (convaiNPC != null && availableTriggers != null && selectedTriggerIndex >= 0 && selectedTriggerIndex < availableTriggers.Count)
|
||||
{
|
||||
string selectedTriggerName = availableTriggers[selectedTriggerIndex];
|
||||
ConvaiNPCManager.Instance.SetActiveConvaiNPC(convaiNPC, false);
|
||||
onTriggerEvent?.Invoke();
|
||||
convaiNPC.TriggerEvent(selectedTriggerName);
|
||||
}
|
||||
}
|
||||
|
||||
public void InvokeSpeech(string message)
|
||||
{
|
||||
if (convaiNPC != null && !string.IsNullOrEmpty(message))
|
||||
{
|
||||
ConvaiNPCManager.Instance.SetActiveConvaiNPC(convaiNPC, false);
|
||||
onTriggerEvent?.Invoke();
|
||||
convaiNPC.TriggerSpeech(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c783ed73e64a204ebf38b93c054b566
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user