Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 716f55c138 | |||
| 4550e85e30 | |||
| ad744301dd | |||
| 28f5409187 | |||
| 3d1772af15 | |||
| a1c052c879 | |||
| 75b8b75590 | |||
| 087f122639 | |||
| afca8cb7e3 | |||
| 8b41d48b7f | |||
| 150f84decd | |||
| a0211d50fc | |||
| 77f7f9ef39 | |||
| c5b9e8e046 | |||
| 5092f7c107 |
@ -34,3 +34,12 @@
|
||||
- Для запуска EditMode/PlayMode-проверок следует использовать `run_tests` и `get_test_job`, если тестовая группа `unityMCP` доступна и это уместно для задачи.
|
||||
- Если нужная группа возможностей `unityMCP` отключена, агент может включить её через `manage_tools`, когда это оправдано задачей.
|
||||
- Если `unityMCP` недоступен, не видит активный Unity Editor, возвращает ошибку или хуже подходит для конкретной операции, агент может использовать файловые инструменты и обычные shell-команды как запасной путь, явно учитывая риск отсутствия проверки внутри Unity.
|
||||
|
||||
## Git Console Output and Chat formatting
|
||||
|
||||
- Никогда не выводите сырой вывод консоли или логов терминала (особенно логи Git) в чат с пользователем.
|
||||
- При выполнении фоновых или синхронных Git-команд перенаправляйте вывод потоков вывода и ошибок в пустоту (заглушайте вывод), чтобы избежать захламления чата системными логами и дублирования строк:
|
||||
- В PowerShell используйте перенаправление в пустоту: `*>$null`
|
||||
- В CMD используйте перенаправление в пустоту: `>nul 2>&1`
|
||||
- Описывайте результаты работы Git понятным человеческим языком на русском языке, перечисляя только суть изменений и конечные статусы, без копирования отчетов терминала.
|
||||
|
||||
|
||||
8
Assets/Editor.meta
Normal file
8
Assets/Editor.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 82f0a4f87da69ea4f86a4841fa5bf39d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
365
Assets/Editor/InjectToonFireToShaderGraph.cs
Normal file
365
Assets/Editor/InjectToonFireToShaderGraph.cs
Normal file
@ -0,0 +1,365 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
public static class InjectToonFireToShaderGraph
|
||||
{
|
||||
[MenuItem("Tools/Inject Toon Fire to Shader Graph")]
|
||||
public static void Inject()
|
||||
{
|
||||
string path = "Assets/Shaders/Fire_Shader.shadergraph";
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
Debug.LogError($"ShaderGraph not found at {path}");
|
||||
return;
|
||||
}
|
||||
|
||||
string jsonText = File.ReadAllText(path);
|
||||
List<JObject> jObjects = new List<JObject>();
|
||||
|
||||
// Parse Multi-JSON using SupportMultipleContent = true
|
||||
using (var stringReader = new StringReader(jsonText))
|
||||
using (var jsonReader = new JsonTextReader(stringReader))
|
||||
{
|
||||
jsonReader.SupportMultipleContent = true;
|
||||
while (jsonReader.Read())
|
||||
{
|
||||
if (jsonReader.TokenType == JsonToken.StartObject)
|
||||
{
|
||||
JObject obj = JObject.Load(jsonReader);
|
||||
jObjects.Add(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find the main GraphData object (usually the first one, but let's be safe)
|
||||
JObject graphData = null;
|
||||
foreach (var obj in jObjects)
|
||||
{
|
||||
if ((string)obj["m_Type"] == "UnityEditor.ShaderGraph.GraphData")
|
||||
{
|
||||
graphData = obj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (graphData == null)
|
||||
{
|
||||
Debug.LogError("Could not find GraphData object in ShaderGraph file!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Remove connections to BaseColor and Alpha block nodes in m_Edges
|
||||
// BaseColor block id: "5795a95f005b46bbbbf4c4e22a0ae9c3"
|
||||
// Alpha block id: "6c0a4ae63e3c48ad9e08ffbc4cf86bba"
|
||||
JArray edges = (JArray)graphData["m_Edges"];
|
||||
List<JToken> edgesToRemove = new List<JToken>();
|
||||
foreach (var edge in edges)
|
||||
{
|
||||
string inputNodeId = (string)edge["m_InputSlot"]["m_Node"]["m_Id"];
|
||||
string outputNodeId = (string)edge["m_OutputSlot"]["m_Node"]["m_Id"];
|
||||
if (inputNodeId == "5795a95f005b46bbbbf4c4e22a0ae9c3" ||
|
||||
inputNodeId == "6c0a4ae63e3c48ad9e08ffbc4cf86bba" ||
|
||||
inputNodeId == "node_cartoon_fire_custom" ||
|
||||
outputNodeId == "node_cartoon_fire_custom")
|
||||
{
|
||||
edgesToRemove.Add(edge);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var edge in edgesToRemove)
|
||||
{
|
||||
edges.Remove(edge);
|
||||
}
|
||||
|
||||
// 2. Define our Custom Function node and Slot JObjects
|
||||
JObject slotInRawValue = JObject.Parse(@"{
|
||||
""m_SGVersion"": 0,
|
||||
""m_Type"": ""UnityEditor.ShaderGraph.Vector1MaterialSlot"",
|
||||
""m_ObjectId"": ""slot_in_raw_value"",
|
||||
""m_Id"": 0,
|
||||
""m_DisplayName"": ""rawValue"",
|
||||
""m_SlotType"": 0,
|
||||
""m_Hidden"": false,
|
||||
""m_ShaderOutputName"": ""rawValue"",
|
||||
""m_StageCapability"": 3,
|
||||
""m_Value"": 0.0,
|
||||
""m_DefaultValue"": 0.0,
|
||||
""m_Labels"": []
|
||||
}");
|
||||
|
||||
JObject slotInBaseColor = JObject.Parse(@"{
|
||||
""m_SGVersion"": 0,
|
||||
""m_Type"": ""UnityEditor.ShaderGraph.Vector4MaterialSlot"",
|
||||
""m_ObjectId"": ""slot_in_base_color"",
|
||||
""m_Id"": 1,
|
||||
""m_DisplayName"": ""baseColor"",
|
||||
""m_SlotType"": 0,
|
||||
""m_Hidden"": false,
|
||||
""m_ShaderOutputName"": ""baseColor"",
|
||||
""m_StageCapability"": 3,
|
||||
""m_Value"": {
|
||||
""x"": 1.0,
|
||||
""y"": 1.0,
|
||||
""z"": 1.0,
|
||||
""w"": 1.0
|
||||
},
|
||||
""m_DefaultValue"": {
|
||||
""x"": 0.0,
|
||||
""y"": 0.0,
|
||||
""z"": 0.0,
|
||||
""w"": 0.0
|
||||
},
|
||||
""m_Labels"": []
|
||||
}");
|
||||
|
||||
JObject slotOutColor = JObject.Parse(@"{
|
||||
""m_SGVersion"": 0,
|
||||
""m_Type"": ""UnityEditor.ShaderGraph.Vector3MaterialSlot"",
|
||||
""m_ObjectId"": ""slot_out_color"",
|
||||
""m_Id"": 2,
|
||||
""m_DisplayName"": ""outColor"",
|
||||
""m_SlotType"": 1,
|
||||
""m_Hidden"": false,
|
||||
""m_ShaderOutputName"": ""outColor"",
|
||||
""m_StageCapability"": 3,
|
||||
""m_Value"": {
|
||||
""x"": 0.0,
|
||||
""y"": 0.0,
|
||||
""z"": 0.0
|
||||
},
|
||||
""m_DefaultValue"": {
|
||||
""x"": 0.0,
|
||||
""y"": 0.0,
|
||||
""z"": 0.0
|
||||
},
|
||||
""m_Labels"": []
|
||||
}");
|
||||
|
||||
JObject slotOutAlpha = JObject.Parse(@"{
|
||||
""m_SGVersion"": 0,
|
||||
""m_Type"": ""UnityEditor.ShaderGraph.Vector1MaterialSlot"",
|
||||
""m_ObjectId"": ""slot_out_alpha"",
|
||||
""m_Id"": 3,
|
||||
""m_DisplayName"": ""outAlpha"",
|
||||
""m_SlotType"": 1,
|
||||
""m_Hidden"": false,
|
||||
""m_ShaderOutputName"": ""outAlpha"",
|
||||
""m_StageCapability"": 3,
|
||||
""m_Value"": 0.0,
|
||||
""m_DefaultValue"": 0.0,
|
||||
""m_Labels"": []
|
||||
}");
|
||||
|
||||
JObject slotInTexAlpha = JObject.Parse(@"{
|
||||
""m_SGVersion"": 0,
|
||||
""m_Type"": ""UnityEditor.ShaderGraph.Vector1MaterialSlot"",
|
||||
""m_ObjectId"": ""slot_in_tex_alpha"",
|
||||
""m_Id"": 4,
|
||||
""m_DisplayName"": ""texAlpha"",
|
||||
""m_SlotType"": 0,
|
||||
""m_Hidden"": false,
|
||||
""m_ShaderOutputName"": ""texAlpha"",
|
||||
""m_StageCapability"": 3,
|
||||
""m_Value"": 1.0,
|
||||
""m_DefaultValue"": 1.0,
|
||||
""m_Labels"": []
|
||||
}");
|
||||
|
||||
JObject customFunctionNode = JObject.Parse(@"{
|
||||
""m_SGVersion"": 1,
|
||||
""m_Type"": ""UnityEditor.ShaderGraph.CustomFunctionNode"",
|
||||
""m_ObjectId"": ""node_cartoon_fire_custom"",
|
||||
""m_Group"": {
|
||||
""m_Id"": """"
|
||||
},
|
||||
""m_Name"": ""ToonFireColor (Custom Function)"",
|
||||
""m_DrawState"": {
|
||||
""m_Expanded"": true,
|
||||
""m_Position"": {
|
||||
""serializedVersion"": ""2"",
|
||||
""x"": -400.0,
|
||||
""y"": 56.0,
|
||||
""width"": 220.0,
|
||||
""height"": 180.0
|
||||
}
|
||||
},
|
||||
""m_Slots"": [
|
||||
{ ""m_Id"": ""slot_in_raw_value"" },
|
||||
{ ""m_Id"": ""slot_in_base_color"" },
|
||||
{ ""m_Id"": ""slot_out_color"" },
|
||||
{ ""m_Id"": ""slot_out_alpha"" },
|
||||
{ ""m_Id"": ""slot_in_tex_alpha"" }
|
||||
],
|
||||
""synonyms"": [],
|
||||
""m_Precision"": 0,
|
||||
""m_PreviewExpanded"": false,
|
||||
""m_DismissedVersion"": 0,
|
||||
""m_PreviewMode"": 0,
|
||||
""m_CustomColors"": {
|
||||
""m_SerializableColors"": []
|
||||
},
|
||||
""m_SourceType"": 1,
|
||||
""m_FunctionName"": ""ToonFireColor"",
|
||||
""m_FunctionSource"": """",
|
||||
""m_FunctionBody"": ""float3 colInner = float3(1.0, 0.95, 0.4) * baseColor.rgb * 2.2;\nfloat3 colMid = float3(1.0, 0.55, 0.0) * baseColor.rgb * 1.8;\nfloat3 colOuter = float3(1.0, 0.15, 0.1) * baseColor.rgb * 1.4;\n\nfloat stepOuter = step(1.0, rawValue);\nfloat stepMid = step(1.12, rawValue);\nfloat stepInner = step(1.25, rawValue);\n\nfloat3 finalColor = float3(0,0,0);\nif (stepInner > 0.5)\n{\n finalColor = colInner;\n}\nelse if (stepMid > 0.5)\n{\n finalColor = colMid;\n}\nelse if (stepOuter > 0.5)\n{\n finalColor = colOuter;\n}\n\noutColor = finalColor;\noutAlpha = stepOuter * baseColor.a;""
|
||||
}");
|
||||
|
||||
// Remove previous instances of our nodes from list (if re-running script)
|
||||
jObjects.RemoveAll(x => (string)x["m_ObjectId"] == "slot_in_raw_value");
|
||||
jObjects.RemoveAll(x => (string)x["m_ObjectId"] == "slot_in_base_color");
|
||||
jObjects.RemoveAll(x => (string)x["m_ObjectId"] == "slot_out_color");
|
||||
jObjects.RemoveAll(x => (string)x["m_ObjectId"] == "slot_out_alpha");
|
||||
jObjects.RemoveAll(x => (string)x["m_ObjectId"] == "slot_in_tex_alpha");
|
||||
jObjects.RemoveAll(x => (string)x["m_ObjectId"] == "node_cartoon_fire_custom");
|
||||
|
||||
// Add them to the list of objects in the file
|
||||
jObjects.Add(slotInRawValue);
|
||||
jObjects.Add(slotInBaseColor);
|
||||
jObjects.Add(slotOutColor);
|
||||
jObjects.Add(slotOutAlpha);
|
||||
jObjects.Add(slotInTexAlpha);
|
||||
jObjects.Add(customFunctionNode);
|
||||
|
||||
// Add the node reference ID to "m_Nodes" array in GraphData
|
||||
JArray nodes = (JArray)graphData["m_Nodes"];
|
||||
bool hasNode = false;
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
if ((string)node["m_Id"] == "node_cartoon_fire_custom")
|
||||
{
|
||||
hasNode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasNode)
|
||||
{
|
||||
JObject nodeRef = new JObject();
|
||||
nodeRef["m_Id"] = "node_cartoon_fire_custom";
|
||||
nodes.Add(nodeRef);
|
||||
}
|
||||
|
||||
// 3. Connect the new edges in GraphData
|
||||
// Edge 1: raw fire shape (AddNode 0d74e8c23ef1428eaf8c38a4c033c563 output slot 2) -> slot_in_raw_value (CustomFunctionNode input slot 0)
|
||||
JObject edge1 = JObject.Parse(@"{
|
||||
""m_OutputSlot"": {
|
||||
""m_Node"": {
|
||||
""m_Id"": ""0d74e8c23ef1428eaf8c38a4c033c563""
|
||||
},
|
||||
""m_SlotId"": 2
|
||||
},
|
||||
""m_InputSlot"": {
|
||||
""m_Node"": {
|
||||
""m_Id"": ""node_cartoon_fire_custom""
|
||||
},
|
||||
""m_SlotId"": 0
|
||||
}
|
||||
}");
|
||||
|
||||
// Edge 2: base color representation (MultiplyNode e48170ea86fb4291b3e4198160139b3e output slot 2) -> slot_in_base_color (CustomFunctionNode input slot 1)
|
||||
JObject edge2 = JObject.Parse(@"{
|
||||
""m_OutputSlot"": {
|
||||
""m_Node"": {
|
||||
""m_Id"": ""e48170ea86fb4291b3e4198160139b3e""
|
||||
},
|
||||
""m_SlotId"": 2
|
||||
},
|
||||
""m_InputSlot"": {
|
||||
""m_Node"": {
|
||||
""m_Id"": ""node_cartoon_fire_custom""
|
||||
},
|
||||
""m_SlotId"": 1
|
||||
}
|
||||
}");
|
||||
|
||||
// Edge 3: CustomFunctionNode outColor (output slot 2) -> BaseColor block node 5795a95f005b46bbbbf4c4e22a0ae9c3 (slot 0)
|
||||
JObject edge3 = JObject.Parse(@"{
|
||||
""m_OutputSlot"": {
|
||||
""m_Node"": {
|
||||
""m_Id"": ""node_cartoon_fire_custom""
|
||||
},
|
||||
""m_SlotId"": 2
|
||||
},
|
||||
""m_InputSlot"": {
|
||||
""m_Node"": {
|
||||
""m_Id"": ""5795a95f005b46bbbbf4c4e22a0ae9c3""
|
||||
},
|
||||
""m_SlotId"": 0
|
||||
}
|
||||
}");
|
||||
|
||||
// Edge 4: CustomFunctionNode outAlpha (output slot 3) -> Alpha block node 6c0a4ae63e3c48ad9e08ffbc4cf86bba (slot 0)
|
||||
JObject edge4 = JObject.Parse(@"{
|
||||
""m_OutputSlot"": {
|
||||
""m_Node"": {
|
||||
""m_Id"": ""node_cartoon_fire_custom""
|
||||
},
|
||||
""m_SlotId"": 3
|
||||
},
|
||||
""m_InputSlot"": {
|
||||
""m_Node"": {
|
||||
""m_Id"": ""6c0a4ae63e3c48ad9e08ffbc4cf86bba""
|
||||
},
|
||||
""m_SlotId"": 0
|
||||
}
|
||||
}");
|
||||
|
||||
// Edge 5: Sample Texture 2D node (3f4b2124cb794f8e970aacc0488fc224 output slot 4 (alpha)) -> slot_in_tex_alpha (CustomFunctionNode input slot 4)
|
||||
JObject edge5 = JObject.Parse(@"{
|
||||
""m_OutputSlot"": {
|
||||
""m_Node"": {
|
||||
""m_Id"": ""3f4b2124cb794f8e970aacc0488fc224""
|
||||
},
|
||||
""m_SlotId"": 4
|
||||
},
|
||||
""m_InputSlot"": {
|
||||
""m_Node"": {
|
||||
""m_Id"": ""node_cartoon_fire_custom""
|
||||
},
|
||||
""m_SlotId"": 4
|
||||
}
|
||||
}");
|
||||
|
||||
edges.Add(edge1);
|
||||
edges.Add(edge2);
|
||||
edges.Add(edge3);
|
||||
edges.Add(edge4);
|
||||
edges.Add(edge5);
|
||||
|
||||
// Write all JObjects back to file separated by two newlines
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < jObjects.Count; i++)
|
||||
{
|
||||
sb.Append(jObjects[i].ToString(Newtonsoft.Json.Formatting.Indented));
|
||||
if (i < jObjects.Count - 1)
|
||||
{
|
||||
sb.Append("\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllText(path, sb.ToString());
|
||||
|
||||
// Restore material shader to original Fire_Shader.shadergraph
|
||||
string materialPath = "Assets/Materials/Fire_Material.mat";
|
||||
Material mat = AssetDatabase.LoadAssetAtPath<Material>(materialPath);
|
||||
if (mat != null)
|
||||
{
|
||||
Shader origShader = Shader.Find("Shader Graphs/Fire_Shader");
|
||||
if (origShader != null)
|
||||
{
|
||||
Undo.RecordObject(mat, "Restore original Fire ShaderGraph");
|
||||
mat.shader = origShader;
|
||||
EditorUtility.SetDirty(mat);
|
||||
}
|
||||
}
|
||||
|
||||
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
|
||||
AssetDatabase.SaveAssets();
|
||||
Debug.Log("Successfully injected Toon Fire Custom Function with Texture Alpha Mask into Fire_Shader.shadergraph!");
|
||||
}
|
||||
}
|
||||
2
Assets/Editor/InjectToonFireToShaderGraph.cs.meta
Normal file
2
Assets/Editor/InjectToonFireToShaderGraph.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99fc5f3bc18a15f40b96011883199d7d
|
||||
174
Assets/Editor/ReplacePlatformWithSign.cs
Normal file
174
Assets/Editor/ReplacePlatformWithSign.cs
Normal file
@ -0,0 +1,174 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.VFX;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Events;
|
||||
using RR.Game2D.Entities;
|
||||
|
||||
public static class ReplacePlatformWithSign
|
||||
{
|
||||
[MenuItem("Tools/Replace Platform with Sign")]
|
||||
public static string Run()
|
||||
{
|
||||
GameObject platformObj = GameObject.Find("Level/Props/Platforms/TriggeringPlatform_2");
|
||||
if (platformObj == null)
|
||||
{
|
||||
platformObj = GameObject.Find("TriggeringPlatform_2");
|
||||
}
|
||||
if (platformObj == null)
|
||||
{
|
||||
Debug.LogError("Error: TriggeringPlatform_2 not found in scene!");
|
||||
return "Error: TriggeringPlatform_2 not found in scene!";
|
||||
}
|
||||
|
||||
GameObject leverObj = GameObject.Find("Level/Props/Lever");
|
||||
if (leverObj == null)
|
||||
{
|
||||
leverObj = GameObject.Find("Lever");
|
||||
}
|
||||
if (leverObj == null)
|
||||
{
|
||||
Debug.LogError("Error: Lever not found in scene!");
|
||||
return "Error: Lever not found in scene!";
|
||||
}
|
||||
|
||||
Transform parentTransform = platformObj.transform.parent;
|
||||
Vector3 position = platformObj.transform.position;
|
||||
|
||||
Sprite signSprite = AssetDatabase.LoadAssetAtPath<Sprite>("Assets/Resources/Sprites/Props/Signs/Signs_Arrow_Left.png");
|
||||
if (signSprite == null)
|
||||
{
|
||||
// Try fallback OLD folder
|
||||
signSprite = AssetDatabase.LoadAssetAtPath<Sprite>("Assets/Resources/Sprites/Props/Signs/OLD/Signs_Arrow_Left.png");
|
||||
}
|
||||
|
||||
if (signSprite == null)
|
||||
{
|
||||
Debug.LogError("Error: Signs_Arrow_Left.png not found in Assets!");
|
||||
return "Error: Signs_Arrow_Left.png not found in Assets!";
|
||||
}
|
||||
|
||||
// Create sign GameObject
|
||||
GameObject signObj = new GameObject("SignLeft");
|
||||
Undo.RegisterCreatedObjectUndo(signObj, "Create SignLeft");
|
||||
signObj.transform.parent = parentTransform;
|
||||
signObj.transform.position = position;
|
||||
signObj.transform.localScale = Vector3.one;
|
||||
|
||||
// Add SpriteRenderer
|
||||
SpriteRenderer sr = signObj.AddComponent<SpriteRenderer>();
|
||||
sr.sprite = signSprite;
|
||||
|
||||
// Copy sorting layer and order from sibling or default
|
||||
SpriteRenderer[] allRenderers = parentTransform.parent.GetComponentsInChildren<SpriteRenderer>(true);
|
||||
if (allRenderers != null && allRenderers.Length > 0)
|
||||
{
|
||||
sr.sortingLayerID = allRenderers[0].sortingLayerID;
|
||||
sr.sortingLayerName = allRenderers[0].sortingLayerName;
|
||||
sr.sortingOrder = allRenderers[0].sortingOrder;
|
||||
}
|
||||
else
|
||||
{
|
||||
sr.sortingLayerName = "Foreground";
|
||||
sr.sortingOrder = 0;
|
||||
}
|
||||
|
||||
// Add ShowObjectWithVFX component
|
||||
ShowObjectWithVFX triggerScript = signObj.AddComponent<ShowObjectWithVFX>();
|
||||
|
||||
// Use reflection to set private serialized fields
|
||||
var targetField = typeof(ShowObjectWithVFX).GetField("targetObject", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
if (targetField != null)
|
||||
{
|
||||
targetField.SetValue(triggerScript, signObj);
|
||||
}
|
||||
|
||||
// Create Sparks ParticleSystem
|
||||
GameObject sparksObj = new GameObject("Sparks");
|
||||
sparksObj.transform.parent = signObj.transform;
|
||||
sparksObj.transform.localPosition = Vector3.zero;
|
||||
|
||||
ParticleSystem ps = sparksObj.AddComponent<ParticleSystem>();
|
||||
|
||||
// Configure particles to look like sparks
|
||||
var main = ps.main;
|
||||
main.duration = 1.0f;
|
||||
main.loop = false;
|
||||
main.startLifetime = new ParticleSystem.MinMaxCurve(0.4f, 0.8f);
|
||||
main.startSpeed = new ParticleSystem.MinMaxCurve(3.0f, 6.0f);
|
||||
main.startSize = new ParticleSystem.MinMaxCurve(0.1f, 0.25f);
|
||||
main.gravityModifier = 0.9f;
|
||||
main.playOnAwake = false;
|
||||
|
||||
var emission = ps.emission;
|
||||
emission.enabled = true;
|
||||
emission.rateOverTime = 0;
|
||||
var burst = new ParticleSystem.Burst(0.0f, 40);
|
||||
emission.SetBursts(new ParticleSystem.Burst[] { burst });
|
||||
|
||||
var shape = ps.shape;
|
||||
shape.enabled = true;
|
||||
shape.shapeType = ParticleSystemShapeType.Cone;
|
||||
shape.angle = 60f;
|
||||
shape.radius = 0.3f;
|
||||
|
||||
var colorOverLifetime = ps.colorOverLifetime;
|
||||
colorOverLifetime.enabled = true;
|
||||
Gradient gradient = new Gradient();
|
||||
gradient.SetKeys(
|
||||
new GradientColorKey[] { new GradientColorKey(new Color(1f, 0.9f, 0.3f), 0.0f), new GradientColorKey(new Color(1f, 0.3f, 0.0f), 1.0f) },
|
||||
new GradientAlphaKey[] { new GradientAlphaKey(1.0f, 0.0f), new GradientAlphaKey(0.0f, 1.0f) }
|
||||
);
|
||||
colorOverLifetime.color = gradient;
|
||||
|
||||
var psr = sparksObj.GetComponent<ParticleSystemRenderer>();
|
||||
if (psr != null)
|
||||
{
|
||||
psr.material = AssetDatabase.GetBuiltinExtraResource<Material>("Default-Particle.mat");
|
||||
}
|
||||
|
||||
// Assign particle system to triggerScript
|
||||
var psField = typeof(ShowObjectWithVFX).GetField("particleSystemComponent", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
if (psField != null)
|
||||
{
|
||||
psField.SetValue(triggerScript, ps);
|
||||
}
|
||||
|
||||
// Set up Lever activation
|
||||
Lever lever = leverObj.GetComponent<Lever>();
|
||||
if (lever != null)
|
||||
{
|
||||
var onActivateField = typeof(Lever).GetField("onActivate", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
|
||||
if (onActivateField != null)
|
||||
{
|
||||
UnityEngine.Events.UnityEvent onActivate = (UnityEngine.Events.UnityEvent)onActivateField.GetValue(lever);
|
||||
if (onActivate != null)
|
||||
{
|
||||
// Clear any old triggers pointing to platform
|
||||
int persistentEventCount = onActivate.GetPersistentEventCount();
|
||||
for (int i = persistentEventCount - 1; i >= 0; i--)
|
||||
{
|
||||
Object target = onActivate.GetPersistentTarget(i);
|
||||
if (target == platformObj || (target is Component comp && comp.gameObject == platformObj))
|
||||
{
|
||||
UnityEventTools.RemovePersistentListener(onActivate, i);
|
||||
}
|
||||
}
|
||||
|
||||
// Bind new activation
|
||||
UnityEventTools.AddPersistentListener(onActivate, triggerScript.Activate);
|
||||
EditorUtility.SetDirty(lever);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy old platform object
|
||||
Undo.DestroyObjectImmediate(platformObj);
|
||||
|
||||
// Mark scene dirty and save
|
||||
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(signObj.scene);
|
||||
UnityEditor.SceneManagement.EditorSceneManager.SaveScene(signObj.scene);
|
||||
|
||||
Debug.Log("Success! TriggeringPlatform_2 replaced with SignLeft, particle system configured, and Lever.onActivate event updated.");
|
||||
return "Success!";
|
||||
}
|
||||
}
|
||||
2
Assets/Editor/ReplacePlatformWithSign.cs.meta
Normal file
2
Assets/Editor/ReplacePlatformWithSign.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 664333a25198dc74bb19121701092ce5
|
||||
162
Assets/Editor/SpriteAssetGenerator.cs
Normal file
162
Assets/Editor/SpriteAssetGenerator.cs
Normal file
@ -0,0 +1,162 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TextCore;
|
||||
using TMPro;
|
||||
|
||||
public static class SpriteAssetGenerator
|
||||
{
|
||||
[MenuItem("Tools/Generate Prize Sprite Assets")]
|
||||
public static void Generate()
|
||||
{
|
||||
string sourceDir = "Assets/Resources/Sprites/UI/Labels";
|
||||
string destDir = "Assets/Resources/Sprite Assets";
|
||||
|
||||
if (!Directory.Exists(destDir))
|
||||
{
|
||||
Directory.CreateDirectory(destDir);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
if (!Directory.Exists(sourceDir))
|
||||
{
|
||||
Debug.LogError($"[SpriteAssetGenerator] Source directory not found: {sourceDir}");
|
||||
return;
|
||||
}
|
||||
|
||||
string[] pngFiles = Directory.GetFiles(sourceDir, "*.png");
|
||||
if (pngFiles.Length == 0)
|
||||
{
|
||||
Debug.LogWarning($"[SpriteAssetGenerator] No PNG files found in {sourceDir}");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string pngPath in pngFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(pngPath);
|
||||
string assetPath = $"{destDir}/{fileNameWithoutExtension}.asset";
|
||||
|
||||
Texture2D sourceTex = AssetDatabase.LoadAssetAtPath<Texture2D>(pngPath);
|
||||
if (sourceTex == null)
|
||||
{
|
||||
Debug.LogWarning($"[SpriteAssetGenerator] Failed to load Texture2D at: {pngPath}");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create new Sprite Asset
|
||||
TMP_SpriteAsset spriteAsset = ScriptableObject.CreateInstance<TMP_SpriteAsset>();
|
||||
spriteAsset.name = fileNameWithoutExtension;
|
||||
spriteAsset.spriteInfoList = new List<TMP_Sprite>();
|
||||
|
||||
// Set version to 1.1.0 to avoid UpgradeSpriteAsset trigger in Awake/UpdateLookupTables
|
||||
var versionField = typeof(TMP_Asset).GetField("m_Version", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
if (versionField != null)
|
||||
{
|
||||
versionField.SetValue(spriteAsset, "1.1.0");
|
||||
}
|
||||
|
||||
spriteAsset.hashCode = TMP_TextUtilities.GetSimpleHashCode(fileNameWithoutExtension);
|
||||
spriteAsset.spriteSheet = sourceTex;
|
||||
|
||||
// Populate tables
|
||||
List<TMP_SpriteGlyph> spriteGlyphTable = new List<TMP_SpriteGlyph>();
|
||||
List<TMP_SpriteCharacter> spriteCharacterTable = new List<TMP_SpriteCharacter>();
|
||||
|
||||
// Get all sprites contained in this texture file
|
||||
Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(pngPath)
|
||||
.Select(x => x as Sprite)
|
||||
.Where(x => x != null)
|
||||
.OrderByDescending(x => x.rect.y)
|
||||
.ThenBy(x => x.rect.x)
|
||||
.ToArray();
|
||||
|
||||
if (sprites.Length == 0)
|
||||
{
|
||||
Debug.LogWarning($"[SpriteAssetGenerator] No sprites sliced inside texture {pngPath}. Make sure it is sliced as Sprite (Multiple) or Sprite (Single).");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Configure FaceInfo to scale the sprites properly
|
||||
float baseHeight = sprites[0].rect.height;
|
||||
FaceInfo faceInfo = spriteAsset.faceInfo;
|
||||
faceInfo.pointSize = (int)baseHeight;
|
||||
faceInfo.scale = 1.0f;
|
||||
faceInfo.ascentLine = baseHeight;
|
||||
faceInfo.capLine = baseHeight * 0.7f;
|
||||
faceInfo.baseline = 0;
|
||||
faceInfo.descentLine = 0;
|
||||
spriteAsset.faceInfo = faceInfo;
|
||||
|
||||
for (int i = 0; i < sprites.Length; i++)
|
||||
{
|
||||
Sprite sprite = sprites[i];
|
||||
|
||||
TMP_SpriteGlyph spriteGlyph = new TMP_SpriteGlyph();
|
||||
spriteGlyph.index = (uint)i;
|
||||
|
||||
float spriteHeight = sprite.rect.height;
|
||||
// Center the sprite vertically around the cap-height (70% of font size)
|
||||
float bearingY = spriteHeight * 0.85f;
|
||||
float bearingX = 0f;
|
||||
|
||||
spriteGlyph.metrics = new GlyphMetrics(sprite.rect.width, sprite.rect.height, bearingX, bearingY, sprite.rect.width);
|
||||
spriteGlyph.glyphRect = new GlyphRect(sprite.rect);
|
||||
spriteGlyph.scale = 1.0f;
|
||||
spriteGlyph.sprite = sprite;
|
||||
|
||||
spriteGlyphTable.Add(spriteGlyph);
|
||||
|
||||
TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(0xFFFE, spriteGlyph);
|
||||
spriteCharacter.name = sprite.name;
|
||||
spriteCharacter.scale = 1.0f;
|
||||
|
||||
spriteCharacterTable.Add(spriteCharacter);
|
||||
}
|
||||
|
||||
spriteAsset.spriteCharacterTable.Clear();
|
||||
spriteAsset.spriteCharacterTable.AddRange(spriteCharacterTable);
|
||||
|
||||
spriteAsset.spriteGlyphTable.Clear();
|
||||
spriteAsset.spriteGlyphTable.AddRange(spriteGlyphTable);
|
||||
|
||||
// Add default material
|
||||
Shader shader = Shader.Find("TextMeshPro/Sprite");
|
||||
if (shader == null)
|
||||
{
|
||||
shader = Shader.Find("UI/Default");
|
||||
}
|
||||
|
||||
if (shader == null)
|
||||
{
|
||||
Debug.LogError("[SpriteAssetGenerator] Shader not found!");
|
||||
continue;
|
||||
}
|
||||
|
||||
Material material = new Material(shader);
|
||||
material.SetTexture(ShaderUtilities.ID_MainTex, sourceTex);
|
||||
material.name = fileNameWithoutExtension + " Material";
|
||||
|
||||
AssetDatabase.CreateAsset(spriteAsset, assetPath);
|
||||
AssetDatabase.AddObjectToAsset(material, spriteAsset);
|
||||
|
||||
spriteAsset.material = material;
|
||||
spriteAsset.UpdateLookupTables();
|
||||
|
||||
EditorUtility.SetDirty(spriteAsset);
|
||||
Debug.Log($"[SpriteAssetGenerator] Created Sprite Asset at: {assetPath} with {sprites.Length} sprites.");
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
2
Assets/Editor/SpriteAssetGenerator.cs.meta
Normal file
2
Assets/Editor/SpriteAssetGenerator.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a63b29edf14d7140b737239be9b3c05
|
||||
@ -45,11 +45,20 @@ Material:
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _DistortStrength: 0.08
|
||||
- _Fade: 0.4
|
||||
- _FireCellsCount: 5
|
||||
- _NoiseScale: 15
|
||||
- _ThresholdInner: 0.58
|
||||
- _ThresholdMid: 0.38
|
||||
- _ThresholdOuter: 0.15
|
||||
m_Colors:
|
||||
- White: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _Color: {r: 2, g: 2, b: 2, a: 1}
|
||||
- _Speed: {r: 0, g: -0.5, b: 0, a: 0}
|
||||
- _ColorInner: {r: 2.2, g: 0.95, b: 0.15, a: 1}
|
||||
- _ColorMid: {r: 1.8, g: 0.55, b: 0, a: 1}
|
||||
- _ColorOuter: {r: 1.5, g: 0.2, b: 0.1, a: 1}
|
||||
- _Speed: {r: 0, g: -1.8, b: 0, a: 0}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
--- !u!114 &3751385830976373873
|
||||
|
||||
@ -4937,7 +4937,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
m_IsActive: 0
|
||||
--- !u!4 &314704398255972110
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -4989,7 +4989,7 @@ VisualEffect:
|
||||
- m_Value: {x: 2, y: 0.019583605, z: 0, w: 1}
|
||||
m_Name: ParticleColor
|
||||
m_Overridden: 1
|
||||
- m_Value: {x: 4, y: 0.20000002, z: 0, w: 1}
|
||||
- m_Value: {x: 766.9961, y: 275.83508, z: 0, w: 1}
|
||||
m_Name: ShaderColor
|
||||
m_Overridden: 1
|
||||
m_Uint:
|
||||
@ -5014,7 +5014,7 @@ VFXRenderer:
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4081737046539047411}
|
||||
m_Enabled: 1
|
||||
m_Enabled: 0
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
@ -5187,7 +5187,7 @@ VisualEffect:
|
||||
- m_Value: {x: 1, y: 0, z: 0, w: 1}
|
||||
m_Name: ParticleColor
|
||||
m_Overridden: 0
|
||||
- m_Value: {x: 2, y: 0.06666667, z: 0, w: 1}
|
||||
- m_Value: {x: 32, y: 1.0666667, z: 0, w: 1}
|
||||
m_Name: ShaderColor
|
||||
m_Overridden: 1
|
||||
m_Uint:
|
||||
|
||||
@ -297,7 +297,7 @@ MonoBehaviour:
|
||||
m_NumColorKeys: 3
|
||||
m_NumAlphaKeys: 3
|
||||
overrideTexture: 1
|
||||
texture: {fileID: 0}
|
||||
texture: {fileID: 2800000, guid: 375a132719b8f114aadcfda6bf62f8b1, type: 3}
|
||||
--- !u!114 &2117915465640148810
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@ -8,6 +8,14 @@ PrefabInstance:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: -7905401754613951787, guid: 6331eaa4049f7fc4a8107649fc474455, type: 3}
|
||||
propertyPath: jumpVFX
|
||||
value:
|
||||
objectReference: {fileID: 8926484042661614526, guid: 2a6298d2789c9b14faf02ffd58da2493, type: 3}
|
||||
- target: {fileID: -7905401754613951787, guid: 6331eaa4049f7fc4a8107649fc474455, type: 3}
|
||||
propertyPath: landingVFX
|
||||
value:
|
||||
objectReference: {fileID: 8926484042661614526, guid: 2a6298d2789c9b14faf02ffd58da2493, type: 3}
|
||||
- target: {fileID: 1088233528469808677, guid: 6331eaa4049f7fc4a8107649fc474455, type: 3}
|
||||
propertyPath: m_Color.b
|
||||
value: 1
|
||||
|
||||
8
Assets/Resources/Sprite Assets.meta
Normal file
8
Assets/Resources/Sprite Assets.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2aff61ec559c014bb6e119d27baf2f6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
106
Assets/Resources/Sprite Assets/Prize.asset
Normal file
106
Assets/Resources/Sprite Assets/Prize.asset
Normal file
@ -0,0 +1,106 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &-7402772468999753049
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Prize Material
|
||||
m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: e3095083c95b2da47993c18127b66b96, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _ColorMask: 15
|
||||
- _CullMode: 0
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UseUIAlphaClip: 0
|
||||
m_Colors:
|
||||
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 84a92b25f83d49b9bc132d206b370281, type: 3}
|
||||
m_Name: Prize
|
||||
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TMP_SpriteAsset
|
||||
m_Version: 1.1.0
|
||||
m_FaceInfo:
|
||||
m_FaceIndex: 0
|
||||
m_FamilyName:
|
||||
m_StyleName:
|
||||
m_PointSize: 283
|
||||
m_Scale: 1
|
||||
m_UnitsPerEM: 0
|
||||
m_LineHeight: 0
|
||||
m_AscentLine: 283
|
||||
m_CapLine: 198.09999
|
||||
m_MeanLine: 0
|
||||
m_Baseline: 0
|
||||
m_DescentLine: 0
|
||||
m_SuperscriptOffset: 0
|
||||
m_SuperscriptSize: 0
|
||||
m_SubscriptOffset: 0
|
||||
m_SubscriptSize: 0
|
||||
m_UnderlineOffset: 0
|
||||
m_UnderlineThickness: 0
|
||||
m_StrikethroughOffset: 0
|
||||
m_StrikethroughThickness: 0
|
||||
m_TabWidth: 0
|
||||
m_Material: {fileID: -7402772468999753049}
|
||||
spriteSheet: {fileID: 2800000, guid: e3095083c95b2da47993c18127b66b96, type: 3}
|
||||
m_SpriteCharacterTable:
|
||||
- m_ElementType: 2
|
||||
m_Unicode: 65534
|
||||
m_GlyphIndex: 0
|
||||
m_Scale: 1
|
||||
m_Name: Prize_0
|
||||
m_GlyphTable:
|
||||
- m_Index: 0
|
||||
m_Metrics:
|
||||
m_Width: 346
|
||||
m_Height: 283
|
||||
m_HorizontalBearingX: 0
|
||||
m_HorizontalBearingY: 240.55
|
||||
m_HorizontalAdvance: 346
|
||||
m_GlyphRect:
|
||||
m_X: 144
|
||||
m_Y: 176
|
||||
m_Width: 346
|
||||
m_Height: 283
|
||||
m_Scale: 1
|
||||
m_AtlasIndex: 0
|
||||
m_ClassDefinitionType: 0
|
||||
sprite: {fileID: 6685656491756494725, guid: e3095083c95b2da47993c18127b66b96, type: 3}
|
||||
spriteInfoList: []
|
||||
fallbackSpriteAssets: []
|
||||
8
Assets/Resources/Sprite Assets/Prize.asset.meta
Normal file
8
Assets/Resources/Sprite Assets/Prize.asset.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3ce0f400e4eae24da335bfef0eaf163
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
106
Assets/Resources/Sprite Assets/Prize_Hopper.asset
Normal file
106
Assets/Resources/Sprite Assets/Prize_Hopper.asset
Normal file
@ -0,0 +1,106 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 84a92b25f83d49b9bc132d206b370281, type: 3}
|
||||
m_Name: Prize_Hopper
|
||||
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TMP_SpriteAsset
|
||||
m_Version: 1.1.0
|
||||
m_FaceInfo:
|
||||
m_FaceIndex: 0
|
||||
m_FamilyName:
|
||||
m_StyleName:
|
||||
m_PointSize: 283
|
||||
m_Scale: 1
|
||||
m_UnitsPerEM: 0
|
||||
m_LineHeight: 0
|
||||
m_AscentLine: 283
|
||||
m_CapLine: 198.09999
|
||||
m_MeanLine: 0
|
||||
m_Baseline: 0
|
||||
m_DescentLine: 0
|
||||
m_SuperscriptOffset: 0
|
||||
m_SuperscriptSize: 0
|
||||
m_SubscriptOffset: 0
|
||||
m_SubscriptSize: 0
|
||||
m_UnderlineOffset: 0
|
||||
m_UnderlineThickness: 0
|
||||
m_StrikethroughOffset: 0
|
||||
m_StrikethroughThickness: 0
|
||||
m_TabWidth: 0
|
||||
m_Material: {fileID: 8613041187514458185}
|
||||
spriteSheet: {fileID: 2800000, guid: ac75678832a3e1b4ba5aa54e6fd12388, type: 3}
|
||||
m_SpriteCharacterTable:
|
||||
- m_ElementType: 2
|
||||
m_Unicode: 65534
|
||||
m_GlyphIndex: 0
|
||||
m_Scale: 1
|
||||
m_Name: Prize_Hopper_0
|
||||
m_GlyphTable:
|
||||
- m_Index: 0
|
||||
m_Metrics:
|
||||
m_Width: 277
|
||||
m_Height: 283
|
||||
m_HorizontalBearingX: 0
|
||||
m_HorizontalBearingY: 240.55
|
||||
m_HorizontalAdvance: 277
|
||||
m_GlyphRect:
|
||||
m_X: 178
|
||||
m_Y: 175
|
||||
m_Width: 277
|
||||
m_Height: 283
|
||||
m_Scale: 1
|
||||
m_AtlasIndex: 0
|
||||
m_ClassDefinitionType: 0
|
||||
sprite: {fileID: -220201777628614610, guid: ac75678832a3e1b4ba5aa54e6fd12388, type: 3}
|
||||
spriteInfoList: []
|
||||
fallbackSpriteAssets: []
|
||||
--- !u!21 &8613041187514458185
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Prize_Hopper Material
|
||||
m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: ac75678832a3e1b4ba5aa54e6fd12388, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _ColorMask: 15
|
||||
- _CullMode: 0
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UseUIAlphaClip: 0
|
||||
m_Colors:
|
||||
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
8
Assets/Resources/Sprite Assets/Prize_Hopper.asset.meta
Normal file
8
Assets/Resources/Sprite Assets/Prize_Hopper.asset.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 490c014c224f28f4b9cbba78a03997ce
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
106
Assets/Resources/Sprite Assets/Prize_Marbles.asset
Normal file
106
Assets/Resources/Sprite Assets/Prize_Marbles.asset
Normal file
@ -0,0 +1,106 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &-4433844605069381581
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Prize_Marbles Material
|
||||
m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: a2253fc821e9c234daa8e92afdfc9e7c, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _ColorMask: 15
|
||||
- _CullMode: 0
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UseUIAlphaClip: 0
|
||||
m_Colors:
|
||||
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 84a92b25f83d49b9bc132d206b370281, type: 3}
|
||||
m_Name: Prize_Marbles
|
||||
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TMP_SpriteAsset
|
||||
m_Version: 1.1.0
|
||||
m_FaceInfo:
|
||||
m_FaceIndex: 0
|
||||
m_FamilyName:
|
||||
m_StyleName:
|
||||
m_PointSize: 295
|
||||
m_Scale: 1
|
||||
m_UnitsPerEM: 0
|
||||
m_LineHeight: 0
|
||||
m_AscentLine: 295
|
||||
m_CapLine: 206.5
|
||||
m_MeanLine: 0
|
||||
m_Baseline: 0
|
||||
m_DescentLine: 0
|
||||
m_SuperscriptOffset: 0
|
||||
m_SuperscriptSize: 0
|
||||
m_SubscriptOffset: 0
|
||||
m_SubscriptSize: 0
|
||||
m_UnderlineOffset: 0
|
||||
m_UnderlineThickness: 0
|
||||
m_StrikethroughOffset: 0
|
||||
m_StrikethroughThickness: 0
|
||||
m_TabWidth: 0
|
||||
m_Material: {fileID: -4433844605069381581}
|
||||
spriteSheet: {fileID: 2800000, guid: a2253fc821e9c234daa8e92afdfc9e7c, type: 3}
|
||||
m_SpriteCharacterTable:
|
||||
- m_ElementType: 2
|
||||
m_Unicode: 65534
|
||||
m_GlyphIndex: 0
|
||||
m_Scale: 1
|
||||
m_Name: Prize_Marbles_0
|
||||
m_GlyphTable:
|
||||
- m_Index: 0
|
||||
m_Metrics:
|
||||
m_Width: 295
|
||||
m_Height: 295
|
||||
m_HorizontalBearingX: 0
|
||||
m_HorizontalBearingY: 250.75
|
||||
m_HorizontalAdvance: 295
|
||||
m_GlyphRect:
|
||||
m_X: 169
|
||||
m_Y: 170
|
||||
m_Width: 295
|
||||
m_Height: 295
|
||||
m_Scale: 1
|
||||
m_AtlasIndex: 0
|
||||
m_ClassDefinitionType: 0
|
||||
sprite: {fileID: -6115330580039227016, guid: a2253fc821e9c234daa8e92afdfc9e7c, type: 3}
|
||||
spriteInfoList: []
|
||||
fallbackSpriteAssets: []
|
||||
8
Assets/Resources/Sprite Assets/Prize_Marbles.asset.meta
Normal file
8
Assets/Resources/Sprite Assets/Prize_Marbles.asset.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9418adc7dbab1b44299f26bbbd2fdff4
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
106
Assets/Resources/Sprite Assets/Prize_QR.asset
Normal file
106
Assets/Resources/Sprite Assets/Prize_QR.asset
Normal file
@ -0,0 +1,106 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 84a92b25f83d49b9bc132d206b370281, type: 3}
|
||||
m_Name: Prize_QR
|
||||
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TMP_SpriteAsset
|
||||
m_Version: 1.1.0
|
||||
m_FaceInfo:
|
||||
m_FaceIndex: 0
|
||||
m_FamilyName:
|
||||
m_StyleName:
|
||||
m_PointSize: 271
|
||||
m_Scale: 1
|
||||
m_UnitsPerEM: 0
|
||||
m_LineHeight: 0
|
||||
m_AscentLine: 271
|
||||
m_CapLine: 189.7
|
||||
m_MeanLine: 0
|
||||
m_Baseline: 0
|
||||
m_DescentLine: 0
|
||||
m_SuperscriptOffset: 0
|
||||
m_SuperscriptSize: 0
|
||||
m_SubscriptOffset: 0
|
||||
m_SubscriptSize: 0
|
||||
m_UnderlineOffset: 0
|
||||
m_UnderlineThickness: 0
|
||||
m_StrikethroughOffset: 0
|
||||
m_StrikethroughThickness: 0
|
||||
m_TabWidth: 0
|
||||
m_Material: {fileID: 7580124773194365788}
|
||||
spriteSheet: {fileID: 2800000, guid: 1d7aa42f6d3c2ea4bb433db905cf6e6e, type: 3}
|
||||
m_SpriteCharacterTable:
|
||||
- m_ElementType: 2
|
||||
m_Unicode: 65534
|
||||
m_GlyphIndex: 0
|
||||
m_Scale: 1
|
||||
m_Name: Prize_QR_0
|
||||
m_GlyphTable:
|
||||
- m_Index: 0
|
||||
m_Metrics:
|
||||
m_Width: 271
|
||||
m_Height: 271
|
||||
m_HorizontalBearingX: 0
|
||||
m_HorizontalBearingY: 230.35
|
||||
m_HorizontalAdvance: 271
|
||||
m_GlyphRect:
|
||||
m_X: 181
|
||||
m_Y: 182
|
||||
m_Width: 271
|
||||
m_Height: 271
|
||||
m_Scale: 1
|
||||
m_AtlasIndex: 0
|
||||
m_ClassDefinitionType: 0
|
||||
sprite: {fileID: -1280765752914891198, guid: 1d7aa42f6d3c2ea4bb433db905cf6e6e, type: 3}
|
||||
spriteInfoList: []
|
||||
fallbackSpriteAssets: []
|
||||
--- !u!21 &7580124773194365788
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Prize_QR Material
|
||||
m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 1d7aa42f6d3c2ea4bb433db905cf6e6e, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _ColorMask: 15
|
||||
- _CullMode: 0
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UseUIAlphaClip: 0
|
||||
m_Colors:
|
||||
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
8
Assets/Resources/Sprite Assets/Prize_QR.asset.meta
Normal file
8
Assets/Resources/Sprite Assets/Prize_QR.asset.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08c741fa79603ea46be62f9e1daceb66
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
106
Assets/Resources/Sprite Assets/Prize_Tickets.asset
Normal file
106
Assets/Resources/Sprite Assets/Prize_Tickets.asset
Normal file
@ -0,0 +1,106 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &-1533674834702946927
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Prize_Tickets Material
|
||||
m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 9ca00dbece4218c459504eab0334a06b, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _ColorMask: 15
|
||||
- _CullMode: 0
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UseUIAlphaClip: 0
|
||||
m_Colors:
|
||||
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 84a92b25f83d49b9bc132d206b370281, type: 3}
|
||||
m_Name: Prize_Tickets
|
||||
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TMP_SpriteAsset
|
||||
m_Version: 1.1.0
|
||||
m_FaceInfo:
|
||||
m_FaceIndex: 0
|
||||
m_FamilyName:
|
||||
m_StyleName:
|
||||
m_PointSize: 317
|
||||
m_Scale: 1
|
||||
m_UnitsPerEM: 0
|
||||
m_LineHeight: 0
|
||||
m_AscentLine: 317
|
||||
m_CapLine: 221.9
|
||||
m_MeanLine: 0
|
||||
m_Baseline: 0
|
||||
m_DescentLine: 0
|
||||
m_SuperscriptOffset: 0
|
||||
m_SuperscriptSize: 0
|
||||
m_SubscriptOffset: 0
|
||||
m_SubscriptSize: 0
|
||||
m_UnderlineOffset: 0
|
||||
m_UnderlineThickness: 0
|
||||
m_StrikethroughOffset: 0
|
||||
m_StrikethroughThickness: 0
|
||||
m_TabWidth: 0
|
||||
m_Material: {fileID: -1533674834702946927}
|
||||
spriteSheet: {fileID: 2800000, guid: 9ca00dbece4218c459504eab0334a06b, type: 3}
|
||||
m_SpriteCharacterTable:
|
||||
- m_ElementType: 2
|
||||
m_Unicode: 65534
|
||||
m_GlyphIndex: 0
|
||||
m_Scale: 1
|
||||
m_Name: Prize_Tickets_0
|
||||
m_GlyphTable:
|
||||
- m_Index: 0
|
||||
m_Metrics:
|
||||
m_Width: 295
|
||||
m_Height: 317
|
||||
m_HorizontalBearingX: 0
|
||||
m_HorizontalBearingY: 269.45
|
||||
m_HorizontalAdvance: 295
|
||||
m_GlyphRect:
|
||||
m_X: 169
|
||||
m_Y: 159
|
||||
m_Width: 295
|
||||
m_Height: 317
|
||||
m_Scale: 1
|
||||
m_AtlasIndex: 0
|
||||
m_ClassDefinitionType: 0
|
||||
sprite: {fileID: -167649136679044476, guid: 9ca00dbece4218c459504eab0334a06b, type: 3}
|
||||
spriteInfoList: []
|
||||
fallbackSpriteAssets: []
|
||||
8
Assets/Resources/Sprite Assets/Prize_Tickets.asset.meta
Normal file
8
Assets/Resources/Sprite Assets/Prize_Tickets.asset.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 81d03856d45a8b84f8950cec300c2e5d
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -37,7 +37,7 @@ TextureImporter:
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
filterMode: 0
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
|
||||
8
Assets/Resources/Sprites/UI/Labels.meta
Normal file
8
Assets/Resources/Sprites/UI/Labels.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c5bc26aa565fb740a068b5d1fdd18cb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Resources/Sprites/UI/Labels/Prize.png
(Stored with Git LFS)
Normal file
BIN
Assets/Resources/Sprites/UI/Labels/Prize.png
(Stored with Git LFS)
Normal file
Binary file not shown.
169
Assets/Resources/Sprites/UI/Labels/Prize.png.meta
Normal file
169
Assets/Resources/Sprites/UI/Labels/Prize.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3095083c95b2da47993c18127b66b96
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 6685656491756494725
|
||||
second: Prize_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: Prize_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 144
|
||||
y: 176
|
||||
width: 346
|
||||
height: 283
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 58f1e69382938cc50800000000000000
|
||||
internalID: 6685656491756494725
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
Prize_0: 6685656491756494725
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Resources/Sprites/UI/Labels/Prize_Hopper.png
(Stored with Git LFS)
Normal file
BIN
Assets/Resources/Sprites/UI/Labels/Prize_Hopper.png
(Stored with Git LFS)
Normal file
Binary file not shown.
173
Assets/Resources/Sprites/UI/Labels/Prize_Hopper.png.meta
Normal file
173
Assets/Resources/Sprites/UI/Labels/Prize_Hopper.png.meta
Normal file
@ -0,0 +1,173 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac75678832a3e1b4ba5aa54e6fd12388
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -220201777628614610
|
||||
second: Prize_Hopper_0
|
||||
- first:
|
||||
213: 5311543218980421935
|
||||
second: Prize_Hopper_1
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: Prize_Hopper_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 178
|
||||
y: 175
|
||||
width: 277
|
||||
height: 283
|
||||
alignment: 0
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: e20798166afa1fcf0800000000000000
|
||||
internalID: -220201777628614610
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 00c876d74e2ccd64b981881478232845
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
Prize_Hopper_0: -220201777628614610
|
||||
Prize_Hopper_1: 5311543218980421935
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Resources/Sprites/UI/Labels/Prize_Marbles.png
(Stored with Git LFS)
Normal file
BIN
Assets/Resources/Sprites/UI/Labels/Prize_Marbles.png
(Stored with Git LFS)
Normal file
Binary file not shown.
169
Assets/Resources/Sprites/UI/Labels/Prize_Marbles.png.meta
Normal file
169
Assets/Resources/Sprites/UI/Labels/Prize_Marbles.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2253fc821e9c234daa8e92afdfc9e7c
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -6115330580039227016
|
||||
second: Prize_Marbles_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: Prize_Marbles_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 169
|
||||
y: 170
|
||||
width: 295
|
||||
height: 295
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 879ada4ec3bf12ba0800000000000000
|
||||
internalID: -6115330580039227016
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
Prize_Marbles_0: -6115330580039227016
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Resources/Sprites/UI/Labels/Prize_QR.png
(Stored with Git LFS)
Normal file
BIN
Assets/Resources/Sprites/UI/Labels/Prize_QR.png
(Stored with Git LFS)
Normal file
Binary file not shown.
169
Assets/Resources/Sprites/UI/Labels/Prize_QR.png.meta
Normal file
169
Assets/Resources/Sprites/UI/Labels/Prize_QR.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d7aa42f6d3c2ea4bb433db905cf6e6e
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -1280765752914891198
|
||||
second: Prize_QR_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: Prize_QR_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 181
|
||||
y: 182
|
||||
width: 271
|
||||
height: 271
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 24ea501655ec93ee0800000000000000
|
||||
internalID: -1280765752914891198
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
Prize_QR_0: -1280765752914891198
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Resources/Sprites/UI/Labels/Prize_Tickets.png
(Stored with Git LFS)
Normal file
BIN
Assets/Resources/Sprites/UI/Labels/Prize_Tickets.png
(Stored with Git LFS)
Normal file
Binary file not shown.
169
Assets/Resources/Sprites/UI/Labels/Prize_Tickets.png.meta
Normal file
169
Assets/Resources/Sprites/UI/Labels/Prize_Tickets.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ca00dbece4218c459504eab0334a06b
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -167649136679044476
|
||||
second: Prize_Tickets_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: Prize_Tickets_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 169
|
||||
y: 159
|
||||
width: 295
|
||||
height: 317
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 48a38599ff36cadf0800000000000000
|
||||
internalID: -167649136679044476
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
Prize_Tickets_0: -167649136679044476
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@ -227,16 +227,16 @@ namespace RR.Game2D.Behaviour
|
||||
if (!CanSpawn())
|
||||
return null;
|
||||
|
||||
GameObject prefab = PickPrefab();
|
||||
if (prefab == null)
|
||||
return null;
|
||||
|
||||
if (!TryPickSpawnPoint(usedSpawnPointIndices, out Transform spawnPoint))
|
||||
return null;
|
||||
|
||||
Vector3 spawnPosition = spawnPoint != null ? spawnPoint.position : transform.position;
|
||||
Quaternion spawnRotation = spawnPoint != null ? spawnPoint.rotation : transform.rotation;
|
||||
|
||||
GameObject prefab = PickPrefab(spawnPosition);
|
||||
if (prefab == null)
|
||||
return null;
|
||||
|
||||
float zAngle = UnityEngine.Random.Range(randomZRotation.x, randomZRotation.y);
|
||||
spawnRotation *= Quaternion.Euler(0f, 0f, zAngle);
|
||||
|
||||
@ -261,16 +261,34 @@ namespace RR.Game2D.Behaviour
|
||||
return true;
|
||||
}
|
||||
|
||||
private GameObject PickPrefab()
|
||||
private GameObject PickPrefab(Vector3 spawnPosition)
|
||||
{
|
||||
// Проверка, находится ли эта точка спавна внутри какой-либо активной зоны переопределения
|
||||
SpawnPrefabEntry[] activePrefabs = prefabs;
|
||||
EntitySpawnerZone matchedZone = null;
|
||||
|
||||
for (int i = 0; i < EntitySpawnerZone.ActiveZones.Count; i++)
|
||||
{
|
||||
EntitySpawnerZone zone = EntitySpawnerZone.ActiveZones[i];
|
||||
if (zone != null && zone.MatchesSpawner(this) && zone.IsPointInside(spawnPosition))
|
||||
{
|
||||
activePrefabs = zone.Prefabs;
|
||||
matchedZone = zone;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (activePrefabs == null || activePrefabs.Length == 0)
|
||||
return null;
|
||||
|
||||
int totalWeight = 0;
|
||||
|
||||
for (int i = 0; i < prefabs.Length; i++)
|
||||
for (int i = 0; i < activePrefabs.Length; i++)
|
||||
{
|
||||
if (prefabs[i].prefab == null)
|
||||
if (activePrefabs[i].prefab == null)
|
||||
continue;
|
||||
|
||||
totalWeight += Mathf.Max(1, prefabs[i].weight);
|
||||
totalWeight += Mathf.Max(1, activePrefabs[i].weight);
|
||||
}
|
||||
|
||||
if (totalWeight <= 0)
|
||||
@ -278,18 +296,30 @@ namespace RR.Game2D.Behaviour
|
||||
|
||||
int randomValue = UnityEngine.Random.Range(0, totalWeight);
|
||||
int currentWeight = 0;
|
||||
GameObject selectedPrefab = null;
|
||||
|
||||
for (int i = 0; i < prefabs.Length; i++)
|
||||
for (int i = 0; i < activePrefabs.Length; i++)
|
||||
{
|
||||
if (prefabs[i].prefab == null)
|
||||
if (activePrefabs[i].prefab == null)
|
||||
continue;
|
||||
|
||||
currentWeight += Mathf.Max(1, prefabs[i].weight);
|
||||
currentWeight += Mathf.Max(1, activePrefabs[i].weight);
|
||||
if (randomValue < currentWeight)
|
||||
return prefabs[i].prefab;
|
||||
{
|
||||
selectedPrefab = activePrefabs[i].prefab;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return prefabs[prefabs.Length - 1].prefab;
|
||||
if (selectedPrefab == null)
|
||||
selectedPrefab = activePrefabs[activePrefabs.Length - 1].prefab;
|
||||
|
||||
if (selectedPrefab != null && matchedZone != null)
|
||||
{
|
||||
Debug.Log($"[EntitySpawner] Спавнер '{gameObject.name}' переопределил префаб для точки {spawnPosition} на '{selectedPrefab.name}' по зоне '{matchedZone.gameObject.name}'.");
|
||||
}
|
||||
|
||||
return selectedPrefab;
|
||||
}
|
||||
|
||||
private bool TryPickSpawnPoint(HashSet<int> usedSpawnPointIndices, out Transform spawnPoint)
|
||||
|
||||
113
Assets/Scripts/Behaviour/EntitySpawnerZone.cs
Normal file
113
Assets/Scripts/Behaviour/EntitySpawnerZone.cs
Normal file
@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RR.Game2D.Behaviour
|
||||
{
|
||||
[RequireComponent(typeof(Collider2D))]
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class EntitySpawnerZone : MonoBehaviour
|
||||
{
|
||||
[Header("Override Prefabs")]
|
||||
[Tooltip("Список префабов, которые будут спавниться вместо оригинальных префабов спавнера внутри этой зоны.")]
|
||||
[SerializeField] private EntitySpawner.SpawnPrefabEntry[] prefabs;
|
||||
|
||||
[Header("Targeting")]
|
||||
[Tooltip("Фильтр по имени GameObject спавнера. Если не пусто, зона будет переопределять только те спавнеры, чье имя содержит этот текст (без учета регистра).")]
|
||||
[SerializeField] private string spawnerNameFilter = "Enemy";
|
||||
|
||||
private Collider2D _collider;
|
||||
|
||||
// Статический список всех активных зон на сцене для быстрого поиска
|
||||
public static readonly List<EntitySpawnerZone> ActiveZones = new();
|
||||
|
||||
public EntitySpawner.SpawnPrefabEntry[] Prefabs => prefabs;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_collider = GetComponent<Collider2D>();
|
||||
// Убеждаемся, что коллайдер является триггером, чтобы не вызывать физических коллизий с персонажами
|
||||
if (_collider != null)
|
||||
{
|
||||
_collider.isTrigger = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
ActiveZones.Add(this);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
ActiveZones.Remove(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет, подходит ли данный спавнер под критерии фильтрации зоны.
|
||||
/// </summary>
|
||||
public bool MatchesSpawner(EntitySpawner spawner)
|
||||
{
|
||||
if (spawner == null)
|
||||
return false;
|
||||
|
||||
if (string.IsNullOrEmpty(spawnerNameFilter))
|
||||
return true;
|
||||
|
||||
return spawner.gameObject.name.IndexOf(spawnerNameFilter, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет, находится ли мировая точка внутри коллайдера зоны.
|
||||
/// </summary>
|
||||
public bool IsPointInside(Vector3 point)
|
||||
{
|
||||
if (_collider == null)
|
||||
{
|
||||
_collider = GetComponent<Collider2D>();
|
||||
}
|
||||
|
||||
if (_collider == null)
|
||||
return false;
|
||||
|
||||
// Если это BoxCollider2D, выполняем точную математическую проверку в локальных координатах.
|
||||
// Это работает надежно в любой момент (даже до первого физического обновления) и не зависит от Z-координаты.
|
||||
if (_collider is BoxCollider2D box)
|
||||
{
|
||||
Vector3 localPoint = transform.InverseTransformPoint(point);
|
||||
return Mathf.Abs(localPoint.x - box.offset.x) <= box.size.x * 0.5f &&
|
||||
Mathf.Abs(localPoint.y - box.offset.y) <= box.size.y * 0.5f;
|
||||
}
|
||||
|
||||
return _collider.OverlapPoint(point);
|
||||
}
|
||||
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
if (_collider == null)
|
||||
{
|
||||
_collider = GetComponent<Collider2D>();
|
||||
}
|
||||
|
||||
if (_collider == null) return;
|
||||
|
||||
// Рисуем оранжевую рамку зоны замены в редакторе
|
||||
Gizmos.color = new Color(1f, 0.5f, 0f, 0.2f);
|
||||
|
||||
if (_collider is BoxCollider2D box)
|
||||
{
|
||||
Vector3 position = transform.TransformPoint(box.offset);
|
||||
Vector3 size = Vector3.Scale(box.size, transform.lossyScale);
|
||||
|
||||
Gizmos.DrawCube(position, size);
|
||||
Gizmos.color = new Color(1f, 0.5f, 0f, 0.8f);
|
||||
Gizmos.DrawWireCube(position, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Для других типов коллайдеров рисуем сферу в центре объекта
|
||||
Gizmos.DrawSphere(transform.position, 0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Behaviour/EntitySpawnerZone.cs.meta
Normal file
2
Assets/Scripts/Behaviour/EntitySpawnerZone.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5c91a3a7ea71314e9c60d5e48b397d4
|
||||
226
Assets/Scripts/Behaviour/PlayerSkinOverride.cs
Normal file
226
Assets/Scripts/Behaviour/PlayerSkinOverride.cs
Normal file
@ -0,0 +1,226 @@
|
||||
using System.Collections.Generic;
|
||||
using RR.Game2D.Core.Managers;
|
||||
using UnityEngine;
|
||||
using UnityEngine.U2D.Animation;
|
||||
|
||||
namespace RR.Game2D.Behaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Заменяет спрайты созданного игрока спрайтами из совместимого prefab-скина.
|
||||
/// Компонент действует только в собственной сцене и не изменяет prefab игрока.
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class PlayerSkinOverride : MonoBehaviour
|
||||
{
|
||||
[Header("Скин игрока")]
|
||||
[Tooltip("Prefab с той же иерархией SpriteRenderer + SpriteSkin, что и у игрока.")]
|
||||
[SerializeField] private GameObject skinPrefab;
|
||||
|
||||
private GameManager _subscribedManager;
|
||||
private GameObject _lastAppliedPlayer;
|
||||
private string _lastReportedProblem;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
SubscribeToPlayerSpawn();
|
||||
TryApplyToCurrentPlayer();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Повторная попытка нужна, если компонент включился раньше GameManager.
|
||||
SubscribeToPlayerSpawn();
|
||||
TryApplyToCurrentPlayer();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
UnsubscribeFromPlayerSpawn();
|
||||
_lastAppliedPlayer = null;
|
||||
}
|
||||
|
||||
private void SubscribeToPlayerSpawn()
|
||||
{
|
||||
GameManager manager = GameManager.Instance;
|
||||
if (_subscribedManager == manager) return;
|
||||
|
||||
UnsubscribeFromPlayerSpawn();
|
||||
if (manager == null) return;
|
||||
|
||||
_subscribedManager = manager;
|
||||
_subscribedManager.PlayerSpawned += OnPlayerSpawned;
|
||||
}
|
||||
|
||||
private void UnsubscribeFromPlayerSpawn()
|
||||
{
|
||||
if (_subscribedManager != null)
|
||||
_subscribedManager.PlayerSpawned -= OnPlayerSpawned;
|
||||
|
||||
_subscribedManager = null;
|
||||
}
|
||||
|
||||
private void TryApplyToCurrentPlayer()
|
||||
{
|
||||
GameObject player = _subscribedManager != null ? _subscribedManager.PlayerObj : null;
|
||||
if (player == null || player.scene != gameObject.scene) return;
|
||||
|
||||
ApplySkin(player);
|
||||
}
|
||||
|
||||
private void OnPlayerSpawned(GameObject player)
|
||||
{
|
||||
if (player == null || player.scene != gameObject.scene) return;
|
||||
|
||||
ApplySkin(player);
|
||||
}
|
||||
|
||||
private void ApplySkin(GameObject player)
|
||||
{
|
||||
if (_lastAppliedPlayer == player) return;
|
||||
|
||||
if (HasAnotherOverrideInScene())
|
||||
{
|
||||
ReportProblem("В сцене найдено несколько активных PlayerSkinOverride. Скин не применён.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (skinPrefab == null)
|
||||
{
|
||||
ReportProblem("Prefab скина не назначен. Используется стандартный скин игрока.", false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (skinPrefab.scene.IsValid())
|
||||
{
|
||||
ReportProblem("В поле Skin Prefab должен быть назначен prefab-ассет, а не объект сцены.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryCollectParts(skinPrefab, "скина", true, out Dictionary<string, SpriteRenderer> skinParts))
|
||||
return;
|
||||
|
||||
if (!TryCollectParts(player, "игрока", false, out Dictionary<string, SpriteRenderer> playerParts))
|
||||
return;
|
||||
|
||||
if (skinParts.Count != playerParts.Count)
|
||||
{
|
||||
ReportProblem(
|
||||
$"Структура скина несовместима с игроком: частей в скине — {skinParts.Count}, " +
|
||||
$"частей у игрока — {playerParts.Count}. Скин не применён.",
|
||||
true);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, SpriteRenderer> skinPart in skinParts)
|
||||
{
|
||||
if (!playerParts.ContainsKey(skinPart.Key))
|
||||
{
|
||||
ReportProblem(
|
||||
$"У игрока отсутствует визуальная часть \"{skinPart.Key}\". Скин не применён.",
|
||||
true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Замена выполняется только после полной проверки, чтобы не получить частично применённый скин.
|
||||
foreach (KeyValuePair<string, SpriteRenderer> skinPart in skinParts)
|
||||
playerParts[skinPart.Key].sprite = skinPart.Value.sprite;
|
||||
|
||||
_lastAppliedPlayer = player;
|
||||
_lastReportedProblem = null;
|
||||
}
|
||||
|
||||
private bool TryCollectParts(
|
||||
GameObject root,
|
||||
string rootDescription,
|
||||
bool requireSprite,
|
||||
out Dictionary<string, SpriteRenderer> parts)
|
||||
{
|
||||
parts = new Dictionary<string, SpriteRenderer>();
|
||||
SpriteSkin[] spriteSkins = root.GetComponentsInChildren<SpriteSkin>(true);
|
||||
|
||||
if (spriteSkins.Length == 0)
|
||||
{
|
||||
ReportProblem(
|
||||
$"В иерархии {rootDescription} \"{root.name}\" не найдено ни одного SpriteSkin.",
|
||||
true);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (SpriteSkin spriteSkin in spriteSkins)
|
||||
{
|
||||
SpriteRenderer spriteRenderer = spriteSkin.GetComponent<SpriteRenderer>();
|
||||
string relativePath = GetRelativePath(root.transform, spriteSkin.transform);
|
||||
|
||||
if (spriteRenderer == null)
|
||||
{
|
||||
ReportProblem(
|
||||
$"На части {rootDescription} \"{relativePath}\" отсутствует SpriteRenderer.",
|
||||
true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (requireSprite && spriteRenderer.sprite == null)
|
||||
{
|
||||
ReportProblem(
|
||||
$"На части {rootDescription} \"{relativePath}\" не назначен Sprite.",
|
||||
true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parts.TryAdd(relativePath, spriteRenderer))
|
||||
{
|
||||
ReportProblem(
|
||||
$"В иерархии {rootDescription} повторяется путь \"{relativePath}\".",
|
||||
true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool HasAnotherOverrideInScene()
|
||||
{
|
||||
PlayerSkinOverride[] overrides = FindObjectsByType<PlayerSkinOverride>(
|
||||
FindObjectsInactive.Exclude,
|
||||
FindObjectsSortMode.None);
|
||||
|
||||
foreach (PlayerSkinOverride candidate in overrides)
|
||||
{
|
||||
if (candidate != this && candidate.gameObject.scene == gameObject.scene)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string GetRelativePath(Transform root, Transform child)
|
||||
{
|
||||
if (root == child) return string.Empty;
|
||||
|
||||
Stack<string> names = new();
|
||||
Transform current = child;
|
||||
|
||||
while (current != null && current != root)
|
||||
{
|
||||
names.Push(current.name);
|
||||
current = current.parent;
|
||||
}
|
||||
|
||||
return string.Join("/", names);
|
||||
}
|
||||
|
||||
private void ReportProblem(string message, bool isError)
|
||||
{
|
||||
if (_lastReportedProblem == message) return;
|
||||
_lastReportedProblem = message;
|
||||
|
||||
string formattedMessage = $"[{nameof(PlayerSkinOverride)}] {message}";
|
||||
if (isError)
|
||||
Debug.LogError(formattedMessage, this);
|
||||
else
|
||||
Debug.LogWarning(formattedMessage, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Behaviour/PlayerSkinOverride.cs.meta
Normal file
2
Assets/Scripts/Behaviour/PlayerSkinOverride.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3784dd4dcbda97c44a85ea59fdee2076
|
||||
67
Assets/Scripts/Entities/Props/ShowObjectWithVFX.cs
Normal file
67
Assets/Scripts/Entities/Props/ShowObjectWithVFX.cs
Normal file
@ -0,0 +1,67 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.VFX;
|
||||
|
||||
namespace RR.Game2D.Entities
|
||||
{
|
||||
public class ShowObjectWithVFX : MonoBehaviour
|
||||
{
|
||||
[Header("Target Settings")]
|
||||
[SerializeField] private GameObject targetObject;
|
||||
[SerializeField] private bool hideOnStart = true;
|
||||
|
||||
[Header("VFX Settings")]
|
||||
[SerializeField] private VisualEffect visualEffect;
|
||||
[SerializeField] private ParticleSystem particleSystemComponent;
|
||||
[SerializeField] private GameObject vfxPrefab;
|
||||
[SerializeField] private float vfxDestroyDelay = 3f;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (hideOnStart && targetObject != null)
|
||||
{
|
||||
targetObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (visualEffect != null)
|
||||
{
|
||||
visualEffect.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (particleSystemComponent != null)
|
||||
{
|
||||
var emission = particleSystemComponent.emission;
|
||||
emission.enabled = false;
|
||||
particleSystemComponent.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
[ContextMenu("Activate")]
|
||||
public void Activate()
|
||||
{
|
||||
if (targetObject != null)
|
||||
{
|
||||
targetObject.SetActive(true);
|
||||
}
|
||||
|
||||
if (visualEffect != null)
|
||||
{
|
||||
visualEffect.gameObject.SetActive(true);
|
||||
visualEffect.Play();
|
||||
}
|
||||
|
||||
if (particleSystemComponent != null)
|
||||
{
|
||||
particleSystemComponent.gameObject.SetActive(true);
|
||||
var emission = particleSystemComponent.emission;
|
||||
emission.enabled = true;
|
||||
particleSystemComponent.Play();
|
||||
}
|
||||
|
||||
if (vfxPrefab != null)
|
||||
{
|
||||
GameObject vfxInstance = Instantiate(vfxPrefab, transform.position, transform.rotation);
|
||||
Destroy(vfxInstance, vfxDestroyDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Entities/Props/ShowObjectWithVFX.cs.meta
Normal file
2
Assets/Scripts/Entities/Props/ShowObjectWithVFX.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49989a9e1bab58c42bf27b3f7eca8d5b
|
||||
@ -162,34 +162,35 @@ namespace RR.Common.UI
|
||||
|
||||
return config.type switch
|
||||
{
|
||||
PrizeType.QRCode => BuildQrPrizeText(manager, config.qrTier),
|
||||
PrizeType.Hopper => $"хоппер, капсул: {Mathf.Max(1, config.hopperCapsuleCount)}",
|
||||
PrizeType.PrizeStand => BuildPrizeStandText(manager),
|
||||
PrizeType.QRCode => BuildQrPrizeSpriteText(manager, config.qrTier),
|
||||
PrizeType.Hopper => $"<sprite=\"Prize_Hopper\" name=\"Prize_Hopper_0\"> x{Mathf.Max(1, config.hopperCapsuleCount)}",
|
||||
PrizeType.PrizeStand => BuildPrizeStandSpriteText(manager),
|
||||
_ => config.type.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
private static string BuildQrPrizeText(PrizeSystemManager manager, QRTier tier)
|
||||
private static string BuildQrPrizeSpriteText(PrizeSystemManager manager, QRTier tier)
|
||||
{
|
||||
string tierText = tier switch
|
||||
{
|
||||
QRTier.Bronze => "бронзовый QR-код",
|
||||
QRTier.Silver => "серебряный QR-код",
|
||||
QRTier.Gold => "золотой QR-код",
|
||||
_ => "QR-код"
|
||||
};
|
||||
|
||||
string prizeText = manager != null ? manager.GetQRCodeModalPrizeText(tier) : string.Empty;
|
||||
bool isTicket = !string.IsNullOrEmpty(prizeText) &&
|
||||
(prizeText.IndexOf("билет", System.StringComparison.OrdinalIgnoreCase) >= 0 ||
|
||||
prizeText.IndexOf("ticket", System.StringComparison.OrdinalIgnoreCase) >= 0);
|
||||
|
||||
string spriteTag = isTicket
|
||||
? "<sprite=\"Prize_Tickets\" name=\"Prize_Tickets_0\">"
|
||||
: "<sprite=\"Prize_QR\" name=\"Prize_QR_0\">";
|
||||
|
||||
return string.IsNullOrWhiteSpace(prizeText)
|
||||
? tierText
|
||||
: $"{tierText}: {prizeText.Trim()}";
|
||||
? spriteTag
|
||||
: $"{spriteTag} {prizeText.Trim()}";
|
||||
}
|
||||
|
||||
private static string BuildPrizeStandText(PrizeSystemManager manager)
|
||||
private static string BuildPrizeStandSpriteText(PrizeSystemManager manager)
|
||||
{
|
||||
string spriteTag = "<sprite=\"Prize_Marbles\" name=\"Prize_Marbles_0\">";
|
||||
PrizeStandSettings settings = manager != null ? manager.GetPrizeStandSettings() : null;
|
||||
int boxCount = settings?.boxes != null ? settings.boxes.Count : 0;
|
||||
return boxCount > 0 ? $"призовая витрина, ячеек: {boxCount}" : "призовая витрина";
|
||||
return boxCount > 0 ? $"{spriteTag} (ячеек: {boxCount})" : spriteTag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,359 +0,0 @@
|
||||
{
|
||||
"m_SGVersion": 3,
|
||||
"m_Type": "UnityEditor.ShaderGraph.GraphData",
|
||||
"m_ObjectId": "bfd41be4768743d49abea9ce9a041ce1",
|
||||
"m_Properties": [],
|
||||
"m_Keywords": [],
|
||||
"m_Dropdowns": [],
|
||||
"m_CategoryData": [
|
||||
{
|
||||
"m_Id": "10f6db50c33e4ea2bb7a18d474e4bbff"
|
||||
}
|
||||
],
|
||||
"m_Nodes": [
|
||||
{
|
||||
"m_Id": "94c186bebeef4d2b9f136112253d8cd5"
|
||||
},
|
||||
{
|
||||
"m_Id": "252fbabf290644db92ce5bee37d0512a"
|
||||
},
|
||||
{
|
||||
"m_Id": "2dcf088eb2824593aefd458b9ff69f99"
|
||||
},
|
||||
{
|
||||
"m_Id": "cdcab024229546818a2d8b4d465e82e6"
|
||||
}
|
||||
],
|
||||
"m_GroupDatas": [],
|
||||
"m_StickyNoteDatas": [],
|
||||
"m_Edges": [],
|
||||
"m_VertexContext": {
|
||||
"m_Position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0
|
||||
},
|
||||
"m_Blocks": [
|
||||
{
|
||||
"m_Id": "94c186bebeef4d2b9f136112253d8cd5"
|
||||
},
|
||||
{
|
||||
"m_Id": "252fbabf290644db92ce5bee37d0512a"
|
||||
},
|
||||
{
|
||||
"m_Id": "2dcf088eb2824593aefd458b9ff69f99"
|
||||
}
|
||||
]
|
||||
},
|
||||
"m_FragmentContext": {
|
||||
"m_Position": {
|
||||
"x": 0.0,
|
||||
"y": 200.0
|
||||
},
|
||||
"m_Blocks": [
|
||||
{
|
||||
"m_Id": "cdcab024229546818a2d8b4d465e82e6"
|
||||
}
|
||||
]
|
||||
},
|
||||
"m_PreviewData": {
|
||||
"serializedMesh": {
|
||||
"m_SerializedMesh": "{\"mesh\":{\"instanceID\":0}}",
|
||||
"m_Guid": ""
|
||||
},
|
||||
"preventRotation": false
|
||||
},
|
||||
"m_Path": "Shader Graphs",
|
||||
"m_GraphPrecision": 1,
|
||||
"m_PreviewMode": 2,
|
||||
"m_OutputNode": {
|
||||
"m_Id": ""
|
||||
},
|
||||
"m_SubDatas": [],
|
||||
"m_ActiveTargets": [
|
||||
{
|
||||
"m_Id": "54c208f34b824035815c4e6157e4325e"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.CategoryData",
|
||||
"m_ObjectId": "10f6db50c33e4ea2bb7a18d474e4bbff",
|
||||
"m_Name": "",
|
||||
"m_ChildObjectList": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.BlockNode",
|
||||
"m_ObjectId": "252fbabf290644db92ce5bee37d0512a",
|
||||
"m_Group": {
|
||||
"m_Id": ""
|
||||
},
|
||||
"m_Name": "VertexDescription.Normal",
|
||||
"m_DrawState": {
|
||||
"m_Expanded": true,
|
||||
"m_Position": {
|
||||
"serializedVersion": "2",
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"width": 0.0,
|
||||
"height": 0.0
|
||||
}
|
||||
},
|
||||
"m_Slots": [
|
||||
{
|
||||
"m_Id": "65da9c62784d4cb19d46bba53309634c"
|
||||
}
|
||||
],
|
||||
"synonyms": [],
|
||||
"m_Precision": 0,
|
||||
"m_PreviewExpanded": true,
|
||||
"m_DismissedVersion": 0,
|
||||
"m_PreviewMode": 0,
|
||||
"m_CustomColors": {
|
||||
"m_SerializableColors": []
|
||||
},
|
||||
"m_SerializedDescriptor": "VertexDescription.Normal"
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.BlockNode",
|
||||
"m_ObjectId": "2dcf088eb2824593aefd458b9ff69f99",
|
||||
"m_Group": {
|
||||
"m_Id": ""
|
||||
},
|
||||
"m_Name": "VertexDescription.Tangent",
|
||||
"m_DrawState": {
|
||||
"m_Expanded": true,
|
||||
"m_Position": {
|
||||
"serializedVersion": "2",
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"width": 0.0,
|
||||
"height": 0.0
|
||||
}
|
||||
},
|
||||
"m_Slots": [
|
||||
{
|
||||
"m_Id": "81df142a9ee645e08cfc667785bf4b7e"
|
||||
}
|
||||
],
|
||||
"synonyms": [],
|
||||
"m_Precision": 0,
|
||||
"m_PreviewExpanded": true,
|
||||
"m_DismissedVersion": 0,
|
||||
"m_PreviewMode": 0,
|
||||
"m_CustomColors": {
|
||||
"m_SerializableColors": []
|
||||
},
|
||||
"m_SerializedDescriptor": "VertexDescription.Tangent"
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 1,
|
||||
"m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalTarget",
|
||||
"m_ObjectId": "54c208f34b824035815c4e6157e4325e",
|
||||
"m_Datas": [],
|
||||
"m_ActiveSubTarget": {
|
||||
"m_Id": "70ee05b7f8f24361a49d9b6ebda7422a"
|
||||
},
|
||||
"m_AllowMaterialOverride": false,
|
||||
"m_SurfaceType": 0,
|
||||
"m_ZTestMode": 4,
|
||||
"m_ZWriteControl": 0,
|
||||
"m_AlphaMode": 0,
|
||||
"m_RenderFace": 2,
|
||||
"m_AlphaClip": false,
|
||||
"m_CastShadows": true,
|
||||
"m_ReceiveShadows": true,
|
||||
"m_DisableTint": false,
|
||||
"m_Sort3DAs2DCompatible": false,
|
||||
"m_AdditionalMotionVectorMode": 0,
|
||||
"m_AlembicMotionVectors": false,
|
||||
"m_SupportsLODCrossFade": false,
|
||||
"m_CustomEditorGUI": "",
|
||||
"m_SupportVFX": false
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.PositionMaterialSlot",
|
||||
"m_ObjectId": "5b35b4eb69ed4bcaa6689ec1d77efabe",
|
||||
"m_Id": 0,
|
||||
"m_DisplayName": "Position",
|
||||
"m_SlotType": 0,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Position",
|
||||
"m_StageCapability": 1,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_DefaultValue": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_Labels": [],
|
||||
"m_Space": 0
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot",
|
||||
"m_ObjectId": "65da9c62784d4cb19d46bba53309634c",
|
||||
"m_Id": 0,
|
||||
"m_DisplayName": "Normal",
|
||||
"m_SlotType": 0,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Normal",
|
||||
"m_StageCapability": 1,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_DefaultValue": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_Labels": [],
|
||||
"m_Space": 0
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 2,
|
||||
"m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalUnlitSubTarget",
|
||||
"m_ObjectId": "70ee05b7f8f24361a49d9b6ebda7422a",
|
||||
"m_KeepLightingVariants": false,
|
||||
"m_DefaultDecalBlending": true,
|
||||
"m_DefaultSSAO": true
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.TangentMaterialSlot",
|
||||
"m_ObjectId": "81df142a9ee645e08cfc667785bf4b7e",
|
||||
"m_Id": 0,
|
||||
"m_DisplayName": "Tangent",
|
||||
"m_SlotType": 0,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Tangent",
|
||||
"m_StageCapability": 1,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_DefaultValue": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_Labels": [],
|
||||
"m_Space": 0
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.BlockNode",
|
||||
"m_ObjectId": "94c186bebeef4d2b9f136112253d8cd5",
|
||||
"m_Group": {
|
||||
"m_Id": ""
|
||||
},
|
||||
"m_Name": "VertexDescription.Position",
|
||||
"m_DrawState": {
|
||||
"m_Expanded": true,
|
||||
"m_Position": {
|
||||
"serializedVersion": "2",
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"width": 0.0,
|
||||
"height": 0.0
|
||||
}
|
||||
},
|
||||
"m_Slots": [
|
||||
{
|
||||
"m_Id": "5b35b4eb69ed4bcaa6689ec1d77efabe"
|
||||
}
|
||||
],
|
||||
"synonyms": [],
|
||||
"m_Precision": 0,
|
||||
"m_PreviewExpanded": true,
|
||||
"m_DismissedVersion": 0,
|
||||
"m_PreviewMode": 0,
|
||||
"m_CustomColors": {
|
||||
"m_SerializableColors": []
|
||||
},
|
||||
"m_SerializedDescriptor": "VertexDescription.Position"
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.BlockNode",
|
||||
"m_ObjectId": "cdcab024229546818a2d8b4d465e82e6",
|
||||
"m_Group": {
|
||||
"m_Id": ""
|
||||
},
|
||||
"m_Name": "SurfaceDescription.BaseColor",
|
||||
"m_DrawState": {
|
||||
"m_Expanded": true,
|
||||
"m_Position": {
|
||||
"serializedVersion": "2",
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"width": 0.0,
|
||||
"height": 0.0
|
||||
}
|
||||
},
|
||||
"m_Slots": [
|
||||
{
|
||||
"m_Id": "eb00736542bf494b858ac57f9e4a3d72"
|
||||
}
|
||||
],
|
||||
"synonyms": [],
|
||||
"m_Precision": 0,
|
||||
"m_PreviewExpanded": true,
|
||||
"m_DismissedVersion": 0,
|
||||
"m_PreviewMode": 0,
|
||||
"m_CustomColors": {
|
||||
"m_SerializableColors": []
|
||||
},
|
||||
"m_SerializedDescriptor": "SurfaceDescription.BaseColor"
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot",
|
||||
"m_ObjectId": "eb00736542bf494b858ac57f9e4a3d72",
|
||||
"m_Id": 0,
|
||||
"m_DisplayName": "Base Color",
|
||||
"m_SlotType": 0,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "BaseColor",
|
||||
"m_StageCapability": 2,
|
||||
"m_Value": {
|
||||
"x": 0.5,
|
||||
"y": 0.5,
|
||||
"z": 0.5
|
||||
},
|
||||
"m_DefaultValue": {
|
||||
"x": 0.5,
|
||||
"y": 0.5,
|
||||
"z": 0.5
|
||||
},
|
||||
"m_Labels": [],
|
||||
"m_ColorMode": 0,
|
||||
"m_DefaultColor": {
|
||||
"r": 0.5,
|
||||
"g": 0.5,
|
||||
"b": 0.5,
|
||||
"a": 1.0
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea1ea5e43c81c7b4285ed77336f302bf
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}
|
||||
useAsTemplate: 0
|
||||
exposeTemplateAsShader: 0
|
||||
template:
|
||||
name:
|
||||
category:
|
||||
description:
|
||||
icon: {instanceID: 0}
|
||||
thumbnail: {instanceID: 0}
|
||||
@ -1,6 +1,8 @@
|
||||
<Solution>
|
||||
<Project Path="MCPForUnity.Runtime.csproj" />
|
||||
<Project Path="VFXGraph.OutputEventHandlers.csproj" />
|
||||
<Project Path="Assembly-CSharp.csproj" />
|
||||
<Project Path="MCPForUnity.Editor.csproj" />
|
||||
<Project Path="Assembly-CSharp-Editor.csproj" />
|
||||
<Project Path="VFXGraph.OutputEventHandlers.Editor.csproj" />
|
||||
</Solution>
|
||||
|
||||
8
Packages/com.coplaydev.unity-mcp/Editor.meta
Normal file
8
Packages/com.coplaydev.unity-mcp/Editor.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 31e7fac5858840340a75cc6df0ad3d9e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3
Packages/com.coplaydev.unity-mcp/Editor/AssemblyInfo.cs
Normal file
3
Packages/com.coplaydev.unity-mcp/Editor/AssemblyInfo.cs
Normal file
@ -0,0 +1,3 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("MCPForUnityTests.EditMode")]
|
||||
11
Packages/com.coplaydev.unity-mcp/Editor/AssemblyInfo.cs.meta
Normal file
11
Packages/com.coplaydev.unity-mcp/Editor/AssemblyInfo.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be61633e00d934610ac1ff8192ffbe3d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/com.coplaydev.unity-mcp/Editor/Clients.meta
Normal file
8
Packages/com.coplaydev.unity-mcp/Editor/Clients.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9d47f01d06964ee7843765d1bd71205
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59ff83375c2c74c8385c4a22549778dd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Constants;
|
||||
using MCPForUnity.Editor.Models;
|
||||
using UnityEditor;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class AntigravityConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public AntigravityConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "Antigravity",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".gemini", "antigravity", "mcp_config.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".gemini", "antigravity", "mcp_config.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".gemini", "antigravity", "mcp_config.json"),
|
||||
HttpUrlProperty = "serverUrl",
|
||||
DefaultUnityFields = { { "disabled", false } },
|
||||
StripEnvWhenNotRequired = true
|
||||
})
|
||||
{ }
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Open Antigravity",
|
||||
"Click the more_horiz menu in the Agent pane > MCP Servers",
|
||||
"Select 'Install' for Unity MCP or use the Configure button above",
|
||||
"Restart Antigravity if necessary"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 331b33961513042e3945d0a1d06615b5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Constants;
|
||||
using MCPForUnity.Editor.Models;
|
||||
using MCPForUnity.Editor.Services;
|
||||
using UnityEditor;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class CherryStudioConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public const string ClientName = "Cherry Studio";
|
||||
|
||||
public CherryStudioConfigurator() : base(new McpClient
|
||||
{
|
||||
name = ClientName,
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Cherry Studio", "config"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support", "Cherry Studio", "config"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config", "Cherry Studio", "config"),
|
||||
SupportsHttpTransport = false
|
||||
})
|
||||
{ }
|
||||
|
||||
public override bool SupportsAutoConfigure => false;
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Open Cherry Studio",
|
||||
"Go to Settings (⚙️) → MCP Server",
|
||||
"Click 'Add Server' button",
|
||||
"For STDIO mode (recommended):",
|
||||
" - Name: unity-mcp",
|
||||
" - Type: STDIO",
|
||||
" - Command: uvx",
|
||||
" - Arguments: Copy from the Manual Configuration JSON below",
|
||||
"Click Save and restart Cherry Studio",
|
||||
"",
|
||||
"Note: Cherry Studio uses UI-based configuration.",
|
||||
"Use the manual snippet below as reference for the values to enter."
|
||||
};
|
||||
|
||||
public override McpStatus CheckStatus(bool attemptAutoRewrite = true)
|
||||
{
|
||||
client.SetStatus(McpStatus.NotConfigured, "Cherry Studio requires manual UI configuration");
|
||||
return client.status;
|
||||
}
|
||||
|
||||
public override void Configure()
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Cherry Studio uses UI-based configuration. " +
|
||||
"Please use the Manual Configuration snippet and Installation Steps to configure manually."
|
||||
);
|
||||
}
|
||||
|
||||
public override string GetManualSnippet()
|
||||
{
|
||||
bool useHttp = EditorConfigurationCache.Instance.UseHttpTransport;
|
||||
|
||||
if (useHttp)
|
||||
{
|
||||
return "# Cherry Studio does not support WebSocket transport.\n" +
|
||||
"# Cherry Studio supports STDIO and SSE transports.\n" +
|
||||
"# \n" +
|
||||
"# To use Cherry Studio:\n" +
|
||||
"# 1. Switch transport to 'Stdio' in Advanced Settings below\n" +
|
||||
"# 2. Return to this configuration screen\n" +
|
||||
"# 3. Copy the STDIO configuration snippet that will appear\n" +
|
||||
"# \n" +
|
||||
"# OPTION 2: SSE mode (future support)\n" +
|
||||
"# Note: Unity MCP does not currently have an SSE endpoint.\n" +
|
||||
"# This may be added in a future update.";
|
||||
}
|
||||
|
||||
return base.GetManualSnippet() + "\n\n" +
|
||||
"# Cherry Studio Configuration Instructions:\n" +
|
||||
"# Cherry Studio uses UI-based configuration, not a JSON file.\n" +
|
||||
"# \n" +
|
||||
"# To configure:\n" +
|
||||
"# 1. Open Cherry Studio\n" +
|
||||
"# 2. Go to Settings (⚙️) → MCP Server\n" +
|
||||
"# 3. Click 'Add Server'\n" +
|
||||
"# 4. Enter the following values from the JSON above:\n" +
|
||||
"# - Name: unity-mcp\n" +
|
||||
"# - Type: STDIO\n" +
|
||||
"# - Command: (copy 'command' value from JSON)\n" +
|
||||
"# - Arguments: (copy 'args' array values, space-separated or as individual entries)\n" +
|
||||
"# - Active: true\n" +
|
||||
"# 5. Click Save\n" +
|
||||
"# 6. Restart Cherry Studio";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6de06c6bb0399154d840a1e4c84be869
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
/// <summary>
|
||||
/// Claude Code configurator using the CLI-based registration (claude mcp add/remove).
|
||||
/// This integrates with Claude Code's native MCP management.
|
||||
/// </summary>
|
||||
public class ClaudeCodeConfigurator : ClaudeCliMcpConfigurator
|
||||
{
|
||||
public ClaudeCodeConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "Claude Code",
|
||||
SupportsHttpTransport = true,
|
||||
})
|
||||
{ }
|
||||
|
||||
public override bool SupportsSkills => true;
|
||||
|
||||
public override string GetSkillInstallPath()
|
||||
{
|
||||
var userHome = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
return Path.Combine(userHome, ".claude", "skills", "unity-mcp-skill");
|
||||
}
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Ensure Claude CLI is installed (comes with Claude Code)",
|
||||
"Click Configure to add UnityMCP via 'claude mcp add'",
|
||||
"The server will be automatically available in Claude Code",
|
||||
"Use Unregister to remove via 'claude mcp remove'"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0d22681fc594475db1c189f2d9abdf7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Constants;
|
||||
using MCPForUnity.Editor.Models;
|
||||
using MCPForUnity.Editor.Services;
|
||||
using UnityEditor;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class ClaudeDesktopConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public const string ClientName = "Claude Desktop";
|
||||
|
||||
public ClaudeDesktopConfigurator() : base(new McpClient
|
||||
{
|
||||
name = ClientName,
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Claude", "claude_desktop_config.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support", "Claude", "claude_desktop_config.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config", "Claude", "claude_desktop_config.json"),
|
||||
SupportsHttpTransport = false,
|
||||
StripEnvWhenNotRequired = true
|
||||
})
|
||||
{ }
|
||||
|
||||
public override bool SupportsSkills => true;
|
||||
|
||||
public override string GetSkillInstallPath()
|
||||
{
|
||||
var userHome = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
return Path.Combine(userHome, ".claude", "skills", "unity-mcp-skill");
|
||||
}
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Open Claude Desktop",
|
||||
"Go to Settings > Developer > Edit Config\nOR open the config path",
|
||||
"Paste the configuration JSON",
|
||||
"Save and restart Claude Desktop"
|
||||
};
|
||||
|
||||
public override void Configure()
|
||||
{
|
||||
bool useHttp = EditorConfigurationCache.Instance.UseHttpTransport;
|
||||
if (useHttp)
|
||||
{
|
||||
throw new InvalidOperationException("Claude Desktop does not support HTTP transport. Switch to stdio in settings before configuring.");
|
||||
}
|
||||
|
||||
base.Configure();
|
||||
}
|
||||
|
||||
public override string GetManualSnippet()
|
||||
{
|
||||
bool useHttp = EditorConfigurationCache.Instance.UseHttpTransport;
|
||||
if (useHttp)
|
||||
{
|
||||
return "# Claude Desktop does not support HTTP transport.\n" +
|
||||
"# In Connect tab, change the Transport option from HTTP to stdio, then regenerate.";
|
||||
}
|
||||
|
||||
return base.GetManualSnippet();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5e5d87c9db57495f842dc366f1ebd65
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class ClineConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public ClineConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "Cline",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support", "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config", "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json"),
|
||||
DefaultUnityFields = { { "disabled", false }, { "autoApprove", new object[] { } } }
|
||||
})
|
||||
{ }
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Open Cline in VS Code",
|
||||
"Click the MCP Servers icon in the Cline pane",
|
||||
"Go to Configure tab and click 'Configure MCP Servers'\nOR open the config file at the path above",
|
||||
"Paste the configuration JSON into the mcpServers object",
|
||||
"Save and restart VS Code"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b8abf0951c7413d9ff97a053b0adf2d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
/// <summary>
|
||||
/// Configures the CodeBuddy CLI (~/.codebuddy.json) MCP settings.
|
||||
/// </summary>
|
||||
public class CodeBuddyCliConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public CodeBuddyCliConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "CodeBuddy CLI",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".codebuddy.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".codebuddy.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".codebuddy.json"),
|
||||
})
|
||||
{ }
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Install CodeBuddy CLI and ensure '~/.codebuddy.json' exists",
|
||||
"Click Configure to add the UnityMCP entry (or manually edit the file above)",
|
||||
"Restart your CLI session if needed"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 923728a98c8c74cfaa6e9203c408f34e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class CodexConfigurator : CodexMcpConfigurator
|
||||
{
|
||||
public CodexConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "Codex",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".codex", "config.toml"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".codex", "config.toml"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".codex", "config.toml")
|
||||
})
|
||||
{ }
|
||||
|
||||
public override bool SupportsSkills => true;
|
||||
|
||||
public override string GetSkillInstallPath()
|
||||
{
|
||||
var userHome = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
return Path.Combine(userHome, ".codex", "skills", "unity-mcp-skill");
|
||||
}
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Run 'codex config edit' in a terminal\nOR open the config file at the path above",
|
||||
"Paste the configuration TOML",
|
||||
"Save and restart Codex"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7037ef8b168e49f79247cb31c3be75a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class CopilotCliConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public CopilotCliConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "GitHub Copilot CLI",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".copilot", "mcp-config.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".copilot", "mcp-config.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".copilot", "mcp-config.json")
|
||||
})
|
||||
{ }
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Install GitHub Copilot CLI (https://docs.github.com/en/copilot/concepts/agents/about-copilot-cli)",
|
||||
"Open or create mcp-config.json at the path above",
|
||||
"Paste the configuration JSON (or use /mcp add in the CLI)",
|
||||
"Restart your Copilot CLI session"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14a4b9a7f749248d496466c2a3a53e56
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class CursorConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public CursorConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "Cursor",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".cursor", "mcp.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".cursor", "mcp.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".cursor", "mcp.json")
|
||||
})
|
||||
{ }
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Open Cursor",
|
||||
"Go to File > Preferences > Cursor Settings > MCP > Add new global MCP server\nOR open the config file at the path above",
|
||||
"Paste the configuration JSON",
|
||||
"Save and restart Cursor"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b708eda314746481fb8f4a1fb0652b03
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Constants;
|
||||
using MCPForUnity.Editor.Models;
|
||||
using UnityEditor;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class GeminiCliConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public GeminiCliConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "Gemini CLI",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".gemini", "settings.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".gemini", "settings.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".gemini", "settings.json"),
|
||||
HttpUrlProperty = "httpUrl",
|
||||
})
|
||||
{ }
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Ensure Gemini CLI is installed (see https://geminicli.com/docs/get-started/installation/)",
|
||||
"Click Register to add UnityMCP via 'gemini mcp add'",
|
||||
"The server will be automatically available in Gemini CLI",
|
||||
"Use Unregister to remove via 'gemini mcp remove'"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5e9bbb45e552453ab5cb557a22d43e7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class KiloCodeConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public KiloCodeConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "Kilo Code",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Code", "User", "globalStorage", "kilocode.kilo-code", "settings", "mcp_settings.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support", "Code", "User", "globalStorage", "kilocode.kilo-code", "settings", "mcp_settings.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config", "Code", "User", "globalStorage", "kilocode.kilo-code", "settings", "mcp_settings.json"),
|
||||
IsVsCodeLayout = false
|
||||
})
|
||||
{ }
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Install Kilo Code extension in VS Code",
|
||||
"Open Kilo Code settings (gear icon in sidebar)",
|
||||
"Navigate to MCP Servers section and click 'Edit Global MCP Settings'\nOR open the config file at the path above",
|
||||
"Paste the configuration JSON into the mcpServers object",
|
||||
"Save and restart VS Code"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3286d62ffe5644f5ea60488fd7e6513d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class KiroConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public KiroConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "Kiro",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".kiro", "settings", "mcp.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".kiro", "settings", "mcp.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".kiro", "settings", "mcp.json"),
|
||||
EnsureEnvObject = true,
|
||||
DefaultUnityFields = { { "disabled", false } }
|
||||
})
|
||||
{ }
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Open Kiro",
|
||||
"Go to File > Settings > Settings > Search for \"MCP\" > Open Workspace MCP Config\nOR open the config file at the path above",
|
||||
"Paste the configuration JSON",
|
||||
"Save and restart Kiro"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9b73ff071a6043dda1f2ec7d682ef71
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,398 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Constants;
|
||||
using MCPForUnity.Editor.Helpers;
|
||||
using MCPForUnity.Editor.Models;
|
||||
using MCPForUnity.Editor.Services;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using UnityEditor;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
/// <summary>
|
||||
/// Configurator for OpenClaw via the openclaw-mcp-bridge plugin.
|
||||
/// OpenClaw stores config at ~/.openclaw/openclaw.json.
|
||||
/// </summary>
|
||||
public class OpenClawConfigurator : McpClientConfiguratorBase
|
||||
{
|
||||
private const string PluginName = "openclaw-mcp-bridge";
|
||||
private const string ServerName = "unityMCP";
|
||||
private const string HttpTransportName = "http";
|
||||
private const string StdioTransportName = "stdio";
|
||||
private const string StdioUrl = "stdio://local";
|
||||
|
||||
public OpenClawConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "OpenClaw",
|
||||
windowsConfigPath = BuildConfigPath(),
|
||||
macConfigPath = BuildConfigPath(),
|
||||
linuxConfigPath = BuildConfigPath()
|
||||
})
|
||||
{ }
|
||||
|
||||
private static string BuildConfigPath()
|
||||
{
|
||||
return Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
|
||||
".openclaw",
|
||||
"openclaw.json");
|
||||
}
|
||||
|
||||
public override string GetConfigPath() => CurrentOsPath();
|
||||
|
||||
public override McpStatus CheckStatus(bool attemptAutoRewrite = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
string path = GetConfigPath();
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
client.SetStatus(McpStatus.NotConfigured);
|
||||
client.configuredTransport = ConfiguredTransport.Unknown;
|
||||
return client.status;
|
||||
}
|
||||
|
||||
JObject root = LoadConfig(path);
|
||||
JObject pluginEntry = root["plugins"]?["entries"]?[PluginName] as JObject;
|
||||
JObject unityServer = FindUnityServer(pluginEntry?["config"]?["servers"]);
|
||||
|
||||
if (pluginEntry == null || unityServer == null)
|
||||
{
|
||||
client.SetStatus(McpStatus.MissingConfig);
|
||||
client.configuredTransport = ConfiguredTransport.Unknown;
|
||||
return client.status;
|
||||
}
|
||||
|
||||
if (!IsEnabled(pluginEntry) || !IsEnabled(unityServer))
|
||||
{
|
||||
client.SetStatus(McpStatus.NotConfigured);
|
||||
client.configuredTransport = ConfiguredTransport.Unknown;
|
||||
return client.status;
|
||||
}
|
||||
|
||||
bool matches = ServerMatchesCurrentEndpoint(unityServer);
|
||||
if (matches)
|
||||
{
|
||||
client.SetStatus(McpStatus.Configured);
|
||||
client.configuredTransport = ResolveTransport(unityServer);
|
||||
return client.status;
|
||||
}
|
||||
|
||||
if (attemptAutoRewrite)
|
||||
{
|
||||
Configure();
|
||||
}
|
||||
else
|
||||
{
|
||||
client.SetStatus(McpStatus.IncorrectPath);
|
||||
client.configuredTransport = ConfiguredTransport.Unknown;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
client.SetStatus(McpStatus.Error, ex.Message);
|
||||
client.configuredTransport = ConfiguredTransport.Unknown;
|
||||
}
|
||||
|
||||
return client.status;
|
||||
}
|
||||
|
||||
public override void Configure()
|
||||
{
|
||||
if (EditorPrefs.GetBool(EditorPrefKeys.LockCursorConfig, false))
|
||||
return;
|
||||
|
||||
string path = GetConfigPath();
|
||||
McpConfigurationHelper.EnsureConfigDirectoryExists(path);
|
||||
|
||||
JObject root = File.Exists(path) ? LoadConfig(path) : new JObject();
|
||||
|
||||
JObject plugins = root["plugins"] as JObject ?? new JObject();
|
||||
root["plugins"] = plugins;
|
||||
|
||||
JObject entries = plugins["entries"] as JObject ?? new JObject();
|
||||
plugins["entries"] = entries;
|
||||
|
||||
JObject pluginEntry = entries[PluginName] as JObject ?? new JObject();
|
||||
entries[PluginName] = pluginEntry;
|
||||
pluginEntry["enabled"] = true;
|
||||
|
||||
JObject pluginConfig = pluginEntry["config"] as JObject ?? new JObject();
|
||||
pluginEntry["config"] = pluginConfig;
|
||||
pluginConfig.Remove("timeout"); // removed in openclaw-mcp-bridge v2+
|
||||
pluginConfig.Remove("retries"); // removed in openclaw-mcp-bridge v2+
|
||||
pluginConfig["servers"] = UpsertUnityServer(pluginConfig["servers"]);
|
||||
|
||||
McpConfigurationHelper.WriteAtomicFile(path, root.ToString(Formatting.Indented));
|
||||
client.SetStatus(McpStatus.Configured);
|
||||
client.configuredTransport = HttpEndpointUtility.GetCurrentServerTransport();
|
||||
}
|
||||
|
||||
public override string GetManualSnippet()
|
||||
{
|
||||
JObject snippet = new JObject
|
||||
{
|
||||
["plugins"] = new JObject
|
||||
{
|
||||
["entries"] = new JObject
|
||||
{
|
||||
[PluginName] = new JObject
|
||||
{
|
||||
["enabled"] = true,
|
||||
["config"] = new JObject
|
||||
{
|
||||
["servers"] = new JObject
|
||||
{
|
||||
[ServerName] = BuildUnityServerEntry()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return snippet.ToString(Formatting.Indented);
|
||||
}
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Install OpenClaw",
|
||||
"Install the bridge plugin: npm install -g openclaw-mcp-bridge (or pnpm add -g openclaw-mcp-bridge)",
|
||||
"In MCP for Unity, choose OpenClaw and click Configure",
|
||||
"OpenClaw uses the currently selected MCP for Unity transport (HTTP or stdio)",
|
||||
"OpenClaw exposes a proxy tool such as unityMCP__call for Unity MCP access",
|
||||
"Restart OpenClaw if the plugin does not hot-reload the new config"
|
||||
};
|
||||
|
||||
private JObject LoadConfig(string path)
|
||||
{
|
||||
string text = File.ReadAllText(path);
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
return new JObject();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject<JObject>(text) ?? new JObject();
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"OpenClaw config contains non-JSON content and cannot be safely auto-edited: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private JObject FindUnityServer(JToken serversToken)
|
||||
{
|
||||
if (serversToken is JObject serverMap)
|
||||
{
|
||||
return serverMap[ServerName] as JObject;
|
||||
}
|
||||
|
||||
if (serversToken is JArray legacyServers)
|
||||
{
|
||||
foreach (JToken token in legacyServers)
|
||||
{
|
||||
JObject server = token as JObject;
|
||||
if (server == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string name = server["name"]?.ToString();
|
||||
if (string.Equals(name, ServerName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return server;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private JObject UpsertUnityServer(JToken serversToken)
|
||||
{
|
||||
JObject servers = NormalizeServers(serversToken);
|
||||
JObject entry = servers[ServerName] as JObject ?? new JObject();
|
||||
JObject desiredEntry = BuildUnityServerEntry();
|
||||
|
||||
entry.Remove("name");
|
||||
entry.Remove("prefix");
|
||||
entry.Remove("healthCheck");
|
||||
entry.Remove("command");
|
||||
entry.Remove("args");
|
||||
entry.Remove("env");
|
||||
entry.Remove("connectTimeoutMs");
|
||||
|
||||
foreach (var property in desiredEntry.Properties())
|
||||
{
|
||||
entry[property.Name] = property.Value.DeepClone();
|
||||
}
|
||||
|
||||
servers[ServerName] = entry;
|
||||
|
||||
return servers;
|
||||
}
|
||||
|
||||
private static JObject NormalizeServers(JToken serversToken)
|
||||
{
|
||||
if (serversToken is JObject serverMap)
|
||||
{
|
||||
return serverMap;
|
||||
}
|
||||
|
||||
var normalized = new JObject();
|
||||
if (!(serversToken is JArray legacyServers))
|
||||
{
|
||||
return normalized;
|
||||
}
|
||||
|
||||
foreach (JToken token in legacyServers)
|
||||
{
|
||||
if (!(token is JObject legacyServer))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string name = legacyServer["name"]?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
normalized[name] = legacyServer;
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private static JObject BuildUnityServerEntry()
|
||||
{
|
||||
ConfiguredTransport transport = HttpEndpointUtility.GetCurrentServerTransport();
|
||||
if (transport == ConfiguredTransport.Stdio)
|
||||
{
|
||||
var (uvxPath, _, packageName) = AssetPathUtility.GetUvxCommandParts();
|
||||
if (string.IsNullOrWhiteSpace(uvxPath))
|
||||
{
|
||||
throw new InvalidOperationException("uvx not found. Install uv/uvx or set the override in Advanced Settings.");
|
||||
}
|
||||
|
||||
var args = new JArray();
|
||||
foreach (string value in AssetPathUtility.GetUvxDevFlagsList())
|
||||
{
|
||||
args.Add(value);
|
||||
}
|
||||
foreach (string value in AssetPathUtility.GetBetaServerFromArgsList())
|
||||
{
|
||||
args.Add(value);
|
||||
}
|
||||
args.Add(packageName);
|
||||
args.Add("--transport");
|
||||
args.Add("stdio");
|
||||
|
||||
return new JObject
|
||||
{
|
||||
["enabled"] = true,
|
||||
["url"] = StdioUrl,
|
||||
["transport"] = StdioTransportName,
|
||||
["command"] = uvxPath,
|
||||
["args"] = args,
|
||||
["toolPrefix"] = ServerName,
|
||||
["requestTimeoutMs"] = 60000,
|
||||
["connectTimeoutMs"] = 15000
|
||||
};
|
||||
}
|
||||
|
||||
return new JObject
|
||||
{
|
||||
["enabled"] = true,
|
||||
["url"] = HttpEndpointUtility.GetMcpRpcUrl(),
|
||||
["transport"] = HttpTransportName,
|
||||
["toolPrefix"] = ServerName,
|
||||
["requestTimeoutMs"] = 30000
|
||||
};
|
||||
}
|
||||
|
||||
private bool ServerMatchesCurrentEndpoint(JObject server)
|
||||
{
|
||||
if (server == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ConfiguredTransport expectedTransport = HttpEndpointUtility.GetCurrentServerTransport();
|
||||
ConfiguredTransport configuredTransport = ResolveTransport(server);
|
||||
if (configuredTransport != expectedTransport)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (configuredTransport == ConfiguredTransport.Stdio)
|
||||
{
|
||||
string configuredUrl = server["url"]?.ToString();
|
||||
string command = server["command"]?.ToString();
|
||||
if (!UrlsEqual(configuredUrl, StdioUrl) || string.IsNullOrWhiteSpace(command))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate the --from package source hasn't drifted (e.g. stable vs prerelease switch)
|
||||
string[] args = (server["args"] as JArray)?.ToObject<string[]>();
|
||||
string configuredSource = McpConfigurationHelper.ExtractUvxUrl(args);
|
||||
string expectedSource = GetExpectedPackageSourceForValidation();
|
||||
if (!string.IsNullOrEmpty(configuredSource) && !string.IsNullOrEmpty(expectedSource) &&
|
||||
!McpConfigurationHelper.PathsEqual(configuredSource, expectedSource))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string configuredUrl = server["url"]?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(configuredUrl) ||
|
||||
(!UrlsEqual(configuredUrl, HttpEndpointUtility.GetLocalMcpRpcUrl()) &&
|
||||
!UrlsEqual(configuredUrl, HttpEndpointUtility.GetRemoteMcpRpcUrl())))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
string toolPrefix = server["toolPrefix"]?.ToString();
|
||||
return string.IsNullOrWhiteSpace(toolPrefix) ||
|
||||
string.Equals(toolPrefix, ServerName, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static bool IsEnabled(JObject entry)
|
||||
{
|
||||
JToken enabledToken = entry["enabled"];
|
||||
return enabledToken == null || enabledToken.Type != JTokenType.Boolean || enabledToken.Value<bool>();
|
||||
}
|
||||
|
||||
private ConfiguredTransport ResolveTransport(JObject server)
|
||||
{
|
||||
string configuredTransport = server?["transport"]?.ToString();
|
||||
string configuredUrl = server?["url"]?.ToString();
|
||||
|
||||
if (string.Equals(configuredTransport, StdioTransportName, StringComparison.OrdinalIgnoreCase) ||
|
||||
UrlsEqual(configuredUrl, StdioUrl))
|
||||
{
|
||||
return ConfiguredTransport.Stdio;
|
||||
}
|
||||
|
||||
if (UrlsEqual(configuredUrl, HttpEndpointUtility.GetRemoteMcpRpcUrl()))
|
||||
{
|
||||
return ConfiguredTransport.HttpRemote;
|
||||
}
|
||||
|
||||
if (UrlsEqual(configuredUrl, HttpEndpointUtility.GetLocalMcpRpcUrl()))
|
||||
{
|
||||
return ConfiguredTransport.Http;
|
||||
}
|
||||
|
||||
return ConfiguredTransport.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19f29c88761345158fc766d24e7c18f3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,224 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Helpers;
|
||||
using MCPForUnity.Editor.Models;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
/// <summary>
|
||||
/// Configurator for OpenCode (opencode.ai) - a Go-based terminal AI coding assistant.
|
||||
/// OpenCode uses ~/.config/opencode/opencode.json with a custom "mcp" format.
|
||||
/// </summary>
|
||||
public class OpenCodeConfigurator : McpClientConfiguratorBase
|
||||
{
|
||||
private const string ServerName = "unityMCP";
|
||||
private const string SchemaUrl = "https://opencode.ai/config.json";
|
||||
private const string RemoteType = "remote";
|
||||
private const string LocalType = "local";
|
||||
|
||||
public OpenCodeConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "OpenCode",
|
||||
windowsConfigPath = BuildConfigPath(),
|
||||
macConfigPath = BuildConfigPath(),
|
||||
linuxConfigPath = BuildConfigPath()
|
||||
})
|
||||
{ }
|
||||
|
||||
private static string BuildConfigPath()
|
||||
{
|
||||
string xdgConfigHome = Environment.GetEnvironmentVariable("XDG_CONFIG_HOME");
|
||||
string configBase = !string.IsNullOrEmpty(xdgConfigHome)
|
||||
? xdgConfigHome
|
||||
: Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config");
|
||||
return Path.Combine(configBase, "opencode", "opencode.json");
|
||||
}
|
||||
|
||||
public override string GetConfigPath() => CurrentOsPath();
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to load and parse the config file.
|
||||
/// Returns null if file doesn't exist or cannot be read.
|
||||
/// Returns parsed JObject if valid JSON found.
|
||||
/// Logs warning if file exists but contains malformed JSON.
|
||||
/// </summary>
|
||||
private JObject TryLoadConfig(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
return null;
|
||||
|
||||
string content;
|
||||
try
|
||||
{
|
||||
content = File.ReadAllText(path);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning($"[OpenCodeConfigurator] Failed to read config file {path}: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject<JObject>(content) ?? new JObject();
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
// Malformed JSON - log warning and return null.
|
||||
// When Configure() receives null, it will do: TryLoadConfig(path) ?? new JObject()
|
||||
// This creates a fresh empty JObject, which replaces the entire file with only the unityMCP section.
|
||||
// Existing config sections are lost. To preserve sections, a different recovery strategy
|
||||
// (e.g., line-by-line parsing, JSON repair, or manual user intervention) would be needed.
|
||||
UnityEngine.Debug.LogWarning($"[OpenCodeConfigurator] Malformed JSON in {path}: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override McpStatus CheckStatus(bool attemptAutoRewrite = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
string path = GetConfigPath();
|
||||
var config = TryLoadConfig(path);
|
||||
|
||||
if (config == null)
|
||||
{
|
||||
client.SetStatus(McpStatus.NotConfigured);
|
||||
return client.status;
|
||||
}
|
||||
|
||||
var unityMcp = config["mcp"]?[ServerName] as JObject;
|
||||
|
||||
if (unityMcp == null)
|
||||
{
|
||||
client.SetStatus(McpStatus.NotConfigured);
|
||||
return client.status;
|
||||
}
|
||||
|
||||
if (EntryMatchesCurrentTransport(unityMcp))
|
||||
{
|
||||
client.SetStatus(McpStatus.Configured);
|
||||
}
|
||||
else if (attemptAutoRewrite)
|
||||
{
|
||||
Configure();
|
||||
}
|
||||
else
|
||||
{
|
||||
client.SetStatus(McpStatus.IncorrectPath);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
client.SetStatus(McpStatus.Error, ex.Message);
|
||||
}
|
||||
|
||||
return client.status;
|
||||
}
|
||||
|
||||
public override void Configure()
|
||||
{
|
||||
try
|
||||
{
|
||||
string path = GetConfigPath();
|
||||
McpConfigurationHelper.EnsureConfigDirectoryExists(path);
|
||||
|
||||
// Load existing config or start fresh, preserving all other properties and MCP servers
|
||||
var config = TryLoadConfig(path) ?? new JObject();
|
||||
|
||||
// Only add $schema if creating a new file
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
config["$schema"] = SchemaUrl;
|
||||
}
|
||||
|
||||
// Preserve existing mcp section and only update our server entry
|
||||
var mcpSection = config["mcp"] as JObject ?? new JObject();
|
||||
config["mcp"] = mcpSection;
|
||||
|
||||
mcpSection[ServerName] = BuildServerEntry();
|
||||
|
||||
McpConfigurationHelper.WriteAtomicFile(path, JsonConvert.SerializeObject(config, Formatting.Indented));
|
||||
client.SetStatus(McpStatus.Configured);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
client.SetStatus(McpStatus.Error, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetManualSnippet()
|
||||
{
|
||||
var snippet = new JObject
|
||||
{
|
||||
["mcp"] = new JObject { [ServerName] = BuildServerEntry() }
|
||||
};
|
||||
return JsonConvert.SerializeObject(snippet, Formatting.Indented);
|
||||
}
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Install OpenCode (https://opencode.ai)",
|
||||
"Click Configure to add Unity MCP to ~/.config/opencode/opencode.json",
|
||||
"Restart OpenCode",
|
||||
"The Unity MCP server should be detected automatically"
|
||||
};
|
||||
|
||||
private static JObject BuildServerEntry()
|
||||
{
|
||||
if (HttpEndpointUtility.GetCurrentServerTransport() == ConfiguredTransport.Stdio)
|
||||
{
|
||||
var (uvxPath, _, packageName) = AssetPathUtility.GetUvxCommandParts();
|
||||
if (string.IsNullOrWhiteSpace(uvxPath))
|
||||
{
|
||||
throw new InvalidOperationException("uvx not found. Install uv/uvx or set the override in Advanced Settings.");
|
||||
}
|
||||
|
||||
var command = new JArray { uvxPath };
|
||||
foreach (string value in AssetPathUtility.GetUvxDevFlagsList())
|
||||
{
|
||||
command.Add(value);
|
||||
}
|
||||
foreach (string value in AssetPathUtility.GetBetaServerFromArgsList())
|
||||
{
|
||||
command.Add(value);
|
||||
}
|
||||
command.Add(packageName);
|
||||
command.Add("--transport");
|
||||
command.Add("stdio");
|
||||
|
||||
return new JObject
|
||||
{
|
||||
["type"] = LocalType,
|
||||
["command"] = command,
|
||||
["enabled"] = true
|
||||
};
|
||||
}
|
||||
|
||||
return new JObject
|
||||
{
|
||||
["type"] = RemoteType,
|
||||
["url"] = HttpEndpointUtility.GetMcpRpcUrl(),
|
||||
["enabled"] = true
|
||||
};
|
||||
}
|
||||
|
||||
private bool EntryMatchesCurrentTransport(JObject entry)
|
||||
{
|
||||
string entryType = entry["type"]?.ToString();
|
||||
ConfiguredTransport expected = HttpEndpointUtility.GetCurrentServerTransport();
|
||||
|
||||
if (expected == ConfiguredTransport.Stdio)
|
||||
{
|
||||
return string.Equals(entryType, LocalType, StringComparison.OrdinalIgnoreCase)
|
||||
&& entry["command"] is JArray;
|
||||
}
|
||||
|
||||
return string.Equals(entryType, RemoteType, StringComparison.OrdinalIgnoreCase)
|
||||
&& UrlsEqual(entry["url"]?.ToString(), HttpEndpointUtility.GetMcpRpcUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 489f99ffb7e6743e88e3203552c8b37b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
/// <summary>
|
||||
/// Qwen Code MCP client configurator.
|
||||
/// Qwen Code uses a JSON-based configuration file with mcpServers section.
|
||||
/// Config path: ~/.qwen/settings.json
|
||||
///
|
||||
/// Qwen Code supports both stdio (uvx) and HTTP transport modes.
|
||||
/// Default: stdio mode (works without Unity Editor for basic operations)
|
||||
/// HTTP mode: requires Unity Editor running with MCP HTTP server started
|
||||
/// </summary>
|
||||
public class QwenCodeConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public QwenCodeConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "Qwen Code",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".qwen", "settings.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".qwen", "settings.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".qwen", "settings.json"),
|
||||
SupportsHttpTransport = true,
|
||||
// Default to stdio transport for Qwen Code (like Cursor)
|
||||
// User can switch to HTTP in Unity: Window > MCP for Unity > Settings
|
||||
})
|
||||
{ }
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Ensure Qwen Code is installed (npm install -g @qwen-code/qwen-code or download from https://github.com/QwenLM/qwen-code)",
|
||||
"Open Qwen Code",
|
||||
"Click 'Auto Configure' to automatically add UnityMCP to settings.json",
|
||||
"OR click 'Manual Setup' to copy the configuration JSON",
|
||||
"Open ~/.qwen/settings.json and paste the configuration",
|
||||
"Save and restart Qwen Code",
|
||||
"Use /mcp command in Qwen Code to verify Unity MCP is connected",
|
||||
"Note: For full functionality, open Unity Editor and start HTTP server"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 46891bcdb00e468cbd04afbfb8f3095e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class RiderConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public RiderConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "Rider GitHub Copilot",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "github-copilot", "intellij", "mcp.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support", "github-copilot", "intellij", "mcp.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config", "github-copilot", "intellij", "mcp.json"),
|
||||
IsVsCodeLayout = true
|
||||
})
|
||||
{ }
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Install GitHub Copilot plugin in Rider",
|
||||
"Open or create mcp.json at the path above",
|
||||
"Paste the configuration JSON",
|
||||
"Save and restart Rider"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2511b0d05271d486bb61f8cc9fd11363
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class TraeConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public TraeConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "Trae",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Trae", "mcp.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support", "Trae", "mcp.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config", "Trae", "mcp.json"),
|
||||
})
|
||||
{ }
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Open Trae and go to Settings > MCP",
|
||||
"Select Add Server > Add Manually",
|
||||
"Paste the JSON or point to the mcp.json file\n"+
|
||||
"Windows: %AppData%\\Trae\\mcp.json\n" +
|
||||
"macOS: ~/Library/Application Support/Trae/mcp.json\n" +
|
||||
"Linux: ~/.config/Trae/mcp.json\n",
|
||||
"Save and restart Trae"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3ab39e22ae0948ab94beae307f9902e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class VSCodeConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public VSCodeConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "VSCode GitHub Copilot",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Code", "User", "mcp.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support", "Code", "User", "mcp.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config", "Code", "User", "mcp.json"),
|
||||
IsVsCodeLayout = true
|
||||
})
|
||||
{ }
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Install GitHub Copilot extension",
|
||||
"Open or create mcp.json at the path above",
|
||||
"Paste the configuration JSON",
|
||||
"Save and restart VSCode"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bcc7ead475a4d4ea2978151c217757b8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class VSCodeInsidersConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public VSCodeInsidersConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "VSCode Insiders GitHub Copilot",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Code - Insiders", "User", "mcp.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support", "Code - Insiders", "User", "mcp.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config", "Code - Insiders", "User", "mcp.json"),
|
||||
IsVsCodeLayout = true
|
||||
})
|
||||
{ }
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Install GitHub Copilot extension in VS Code Insiders",
|
||||
"Open or create mcp.json at the path above",
|
||||
"Paste the configuration JSON",
|
||||
"Save and restart VS Code Insiders"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c4a1b0d3b34489cbf0f8c40c49c4f3b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients.Configurators
|
||||
{
|
||||
public class WindsurfConfigurator : JsonFileMcpConfigurator
|
||||
{
|
||||
public WindsurfConfigurator() : base(new McpClient
|
||||
{
|
||||
name = "Windsurf",
|
||||
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".codeium", "windsurf", "mcp_config.json"),
|
||||
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".codeium", "windsurf", "mcp_config.json"),
|
||||
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".codeium", "windsurf", "mcp_config.json"),
|
||||
HttpUrlProperty = "serverUrl",
|
||||
DefaultUnityFields = { { "disabled", false } },
|
||||
StripEnvWhenNotRequired = true
|
||||
})
|
||||
{ }
|
||||
|
||||
public override IList<string> GetInstallationSteps() => new List<string>
|
||||
{
|
||||
"Open Windsurf",
|
||||
"Go to File > Preferences > Windsurf Settings > MCP > Manage MCPs > View raw config\nOR open the config file at the path above",
|
||||
"Paste the configuration JSON",
|
||||
"Save and restart Windsurf"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b528971e189f141d38db577f155bd222
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,53 @@
|
||||
using MCPForUnity.Editor.Models;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients
|
||||
{
|
||||
/// <summary>
|
||||
/// Contract for MCP client configurators. Each client is responsible for
|
||||
/// status detection, auto-configure, and manual snippet/steps.
|
||||
/// </summary>
|
||||
public interface IMcpClientConfigurator
|
||||
{
|
||||
/// <summary>Stable identifier (e.g., "cursor").</summary>
|
||||
string Id { get; }
|
||||
|
||||
/// <summary>Display name shown in the UI.</summary>
|
||||
string DisplayName { get; }
|
||||
|
||||
/// <summary>Current status cached by the configurator.</summary>
|
||||
McpStatus Status { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The transport type the client is currently configured for.
|
||||
/// Returns Unknown if the client is not configured or the transport cannot be determined.
|
||||
/// </summary>
|
||||
ConfiguredTransport ConfiguredTransport { get; }
|
||||
|
||||
/// <summary>True if this client supports auto-configure.</summary>
|
||||
bool SupportsAutoConfigure { get; }
|
||||
|
||||
/// <summary>Label to show on the configure button for the current state.</summary>
|
||||
string GetConfigureActionLabel();
|
||||
|
||||
/// <summary>Returns the platform-specific config path (or message for CLI-managed clients).</summary>
|
||||
string GetConfigPath();
|
||||
|
||||
/// <summary>Checks and updates status; returns current status.</summary>
|
||||
McpStatus CheckStatus(bool attemptAutoRewrite = true);
|
||||
|
||||
/// <summary>Runs auto-configuration (register/write file/CLI etc.).</summary>
|
||||
void Configure();
|
||||
|
||||
/// <summary>Returns the manual configuration snippet (JSON/TOML/commands).</summary>
|
||||
string GetManualSnippet();
|
||||
|
||||
/// <summary>Returns ordered human-readable installation steps.</summary>
|
||||
System.Collections.Generic.IList<string> GetInstallationSteps();
|
||||
|
||||
/// <summary>True if this client supports skill installation/sync.</summary>
|
||||
bool SupportsSkills { get; }
|
||||
|
||||
/// <summary>Returns the absolute path where skills should be installed, or null if unsupported.</summary>
|
||||
string GetSkillInstallPath();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5a5078d9e6e14027a1abfebf4018634
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d408fd7733cb4a1eb80f785307db2ff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MCPForUnity.Editor.Helpers;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MCPForUnity.Editor.Clients
|
||||
{
|
||||
/// <summary>
|
||||
/// Central registry that auto-discovers configurators via TypeCache.
|
||||
/// </summary>
|
||||
public static class McpClientRegistry
|
||||
{
|
||||
private static List<IMcpClientConfigurator> cached;
|
||||
|
||||
public static IReadOnlyList<IMcpClientConfigurator> All
|
||||
{
|
||||
get
|
||||
{
|
||||
if (cached == null)
|
||||
{
|
||||
cached = BuildRegistry();
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<IMcpClientConfigurator> BuildRegistry()
|
||||
{
|
||||
var configurators = new List<IMcpClientConfigurator>();
|
||||
|
||||
foreach (var type in TypeCache.GetTypesDerivedFrom<IMcpClientConfigurator>())
|
||||
{
|
||||
if (type.IsAbstract || !type.IsClass || !type.IsPublic)
|
||||
continue;
|
||||
|
||||
// Require a public parameterless constructor
|
||||
if (type.GetConstructor(Type.EmptyTypes) == null)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
if (Activator.CreateInstance(type) is IMcpClientConfigurator instance)
|
||||
{
|
||||
configurators.Add(instance);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
McpLog.Warn($"UnityMCP: Failed to instantiate configurator {type.Name}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// Alphabetical order by display name
|
||||
configurators = configurators.OrderBy(c => c.DisplayName, StringComparer.OrdinalIgnoreCase).ToList();
|
||||
return configurators;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ce08555f995e4e848a826c63f18cb35
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/com.coplaydev.unity-mcp/Editor/Constants.meta
Normal file
8
Packages/com.coplaydev.unity-mcp/Editor/Constants.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7e009cbf3e74f6c987331c2b438ec59
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user