feat: add Unity 6 client with 2.5D visual system
Unity client features: - WebSocket connection via NativeWebSocket - 2.5D agent visuals with programmatic placeholder sprites - Billboard system for sprites and UI elements - Floating UI panels (name, HP, energy bars) - Speech bubble system with pop-in animation - RTS-style camera controller (WASD + scroll zoom) - Editor tools for prefab creation and scene setup Scripts: - NetworkManager: WebSocket singleton - GameManager: Agent spawning and event handling - AgentVisual: 2.5D sprite and UI creation - Billboard: Camera-facing behavior - SpeechBubble: Animated dialogue display - CameraController: RTS camera with UI input detection - UIManager: HUD and command input 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
275
unity-client/Assets/Editor/AgentPrefabCreator.cs
Normal file
275
unity-client/Assets/Editor/AgentPrefabCreator.cs
Normal file
@@ -0,0 +1,275 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using TheIsland.Visual;
|
||||
|
||||
namespace TheIsland.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Editor utility for creating and updating Agent prefabs.
|
||||
/// Access via menu: The Island > Create Agent Prefab
|
||||
/// </summary>
|
||||
public class AgentPrefabCreator : EditorWindow
|
||||
{
|
||||
private Sprite characterSprite;
|
||||
private string prefabName = "AgentPrefab";
|
||||
private Color agentColor = new Color(0.3f, 0.6f, 0.9f);
|
||||
private bool createWithPlaceholder = true;
|
||||
|
||||
[MenuItem("The Island/Create Agent Prefab")]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
var window = GetWindow<AgentPrefabCreator>("Agent Prefab Creator");
|
||||
window.minSize = new Vector2(350, 300);
|
||||
}
|
||||
|
||||
[MenuItem("The Island/Quick Create Agent Prefab")]
|
||||
public static void QuickCreatePrefab()
|
||||
{
|
||||
CreateAgentPrefab("AgentPrefab", null, true);
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
EditorGUILayout.Space(10);
|
||||
EditorGUILayout.LabelField("Agent Prefab Creator", EditorStyles.boldLabel);
|
||||
EditorGUILayout.Space(5);
|
||||
|
||||
EditorGUILayout.HelpBox(
|
||||
"Creates a new Agent prefab with:\n" +
|
||||
"- 2D Sprite with Billboard\n" +
|
||||
"- Floating UI (Name, HP, Energy bars)\n" +
|
||||
"- Speech Bubble system\n" +
|
||||
"- Click interaction",
|
||||
MessageType.Info);
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
// Prefab name
|
||||
prefabName = EditorGUILayout.TextField("Prefab Name", prefabName);
|
||||
|
||||
EditorGUILayout.Space(5);
|
||||
|
||||
// Sprite selection
|
||||
createWithPlaceholder = EditorGUILayout.Toggle("Use Placeholder Sprite", createWithPlaceholder);
|
||||
|
||||
if (!createWithPlaceholder)
|
||||
{
|
||||
characterSprite = (Sprite)EditorGUILayout.ObjectField(
|
||||
"Character Sprite",
|
||||
characterSprite,
|
||||
typeof(Sprite),
|
||||
false
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
agentColor = EditorGUILayout.ColorField("Placeholder Color", agentColor);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space(20);
|
||||
|
||||
// Create button
|
||||
if (GUILayout.Button("Create Prefab", GUILayout.Height(35)))
|
||||
{
|
||||
CreateAgentPrefab(prefabName, characterSprite, createWithPlaceholder);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
EditorGUILayout.HelpBox(
|
||||
"Prefab will be saved to: Assets/Prefabs/\n\n" +
|
||||
"After creation:\n" +
|
||||
"1. Assign the prefab to GameManager.agentPrefab\n" +
|
||||
"2. (Optional) Replace placeholder sprite later",
|
||||
MessageType.None);
|
||||
}
|
||||
|
||||
private static void CreateAgentPrefab(string name, Sprite sprite, bool usePlaceholder)
|
||||
{
|
||||
// Ensure Prefabs folder exists
|
||||
string prefabFolder = "Assets/Prefabs";
|
||||
if (!AssetDatabase.IsValidFolder(prefabFolder))
|
||||
{
|
||||
AssetDatabase.CreateFolder("Assets", "Prefabs");
|
||||
}
|
||||
|
||||
// Create root GameObject
|
||||
GameObject agentRoot = new GameObject(name);
|
||||
|
||||
// Add AgentVisual component - it will create all visuals automatically
|
||||
AgentVisual visual = agentRoot.AddComponent<AgentVisual>();
|
||||
|
||||
// If sprite is provided, we need to set it via SerializedObject
|
||||
if (!usePlaceholder && sprite != null)
|
||||
{
|
||||
SerializedObject so = new SerializedObject(visual);
|
||||
SerializedProperty spriteProp = so.FindProperty("characterSprite");
|
||||
if (spriteProp != null)
|
||||
{
|
||||
spriteProp.objectReferenceValue = sprite;
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
}
|
||||
|
||||
// Save as prefab
|
||||
string prefabPath = $"{prefabFolder}/{name}.prefab";
|
||||
|
||||
// Check if prefab already exists
|
||||
GameObject existingPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
||||
if (existingPrefab != null)
|
||||
{
|
||||
if (!EditorUtility.DisplayDialog("Prefab Exists",
|
||||
$"A prefab named '{name}' already exists. Overwrite?",
|
||||
"Overwrite", "Cancel"))
|
||||
{
|
||||
DestroyImmediate(agentRoot);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Save prefab
|
||||
GameObject prefab = PrefabUtility.SaveAsPrefabAsset(agentRoot, prefabPath);
|
||||
|
||||
// Cleanup scene object
|
||||
DestroyImmediate(agentRoot);
|
||||
|
||||
// Select the new prefab
|
||||
Selection.activeObject = prefab;
|
||||
EditorGUIUtility.PingObject(prefab);
|
||||
|
||||
Debug.Log($"[AgentPrefabCreator] Created prefab at: {prefabPath}");
|
||||
EditorUtility.DisplayDialog("Success",
|
||||
$"Agent prefab created at:\n{prefabPath}\n\n" +
|
||||
"Don't forget to assign it to GameManager!",
|
||||
"OK");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Additional menu items for quick actions.
|
||||
/// </summary>
|
||||
public static class IslandEditorMenus
|
||||
{
|
||||
[MenuItem("The Island/Setup Scene")]
|
||||
public static void SetupScene()
|
||||
{
|
||||
// Check for Camera
|
||||
Camera mainCam = Camera.main;
|
||||
if (mainCam == null)
|
||||
{
|
||||
GameObject camObj = new GameObject("Main Camera");
|
||||
mainCam = camObj.AddComponent<Camera>();
|
||||
camObj.tag = "MainCamera";
|
||||
}
|
||||
|
||||
// Add CameraController if not present
|
||||
if (mainCam.GetComponent<TheIsland.Core.CameraController>() == null)
|
||||
{
|
||||
mainCam.gameObject.AddComponent<TheIsland.Core.CameraController>();
|
||||
Debug.Log("[Setup] Added CameraController to Main Camera");
|
||||
}
|
||||
|
||||
// Set camera position and rotation for isometric view
|
||||
mainCam.transform.position = new Vector3(0, 15, -10);
|
||||
mainCam.transform.rotation = Quaternion.Euler(50, 0, 0);
|
||||
mainCam.backgroundColor = new Color(0.4f, 0.6f, 0.9f); // Sky blue
|
||||
mainCam.clearFlags = CameraClearFlags.SolidColor;
|
||||
|
||||
// Create ground plane if not exists
|
||||
if (GameObject.Find("Ground") == null)
|
||||
{
|
||||
GameObject ground = GameObject.CreatePrimitive(PrimitiveType.Plane);
|
||||
ground.name = "Ground";
|
||||
ground.transform.position = Vector3.zero;
|
||||
ground.transform.localScale = new Vector3(5, 1, 5);
|
||||
|
||||
// Set ground material color
|
||||
var renderer = ground.GetComponent<Renderer>();
|
||||
if (renderer != null)
|
||||
{
|
||||
Material mat = new Material(Shader.Find("Standard"));
|
||||
mat.color = new Color(0.3f, 0.5f, 0.3f); // Grass green
|
||||
renderer.material = mat;
|
||||
}
|
||||
|
||||
Debug.Log("[Setup] Created Ground plane");
|
||||
}
|
||||
|
||||
// Create Agent Container if not exists
|
||||
if (GameObject.Find("Agents") == null)
|
||||
{
|
||||
GameObject container = new GameObject("Agents");
|
||||
container.transform.position = Vector3.zero;
|
||||
Debug.Log("[Setup] Created Agents container");
|
||||
}
|
||||
|
||||
Debug.Log("[Setup] Scene setup complete!");
|
||||
EditorUtility.DisplayDialog("Scene Setup",
|
||||
"Scene has been configured with:\n" +
|
||||
"- Camera with CameraController\n" +
|
||||
"- Sky blue background\n" +
|
||||
"- Ground plane\n" +
|
||||
"- Agents container",
|
||||
"OK");
|
||||
}
|
||||
|
||||
[MenuItem("The Island/Setup Managers")]
|
||||
public static void SetupManagers()
|
||||
{
|
||||
// Create NetworkManager
|
||||
if (Object.FindFirstObjectByType<TheIsland.Network.NetworkManager>() == null)
|
||||
{
|
||||
GameObject netMgr = new GameObject("NetworkManager");
|
||||
netMgr.AddComponent<TheIsland.Network.NetworkManager>();
|
||||
Debug.Log("[Setup] Created NetworkManager");
|
||||
}
|
||||
|
||||
// Create GameManager
|
||||
if (Object.FindFirstObjectByType<TheIsland.Core.GameManager>() == null)
|
||||
{
|
||||
GameObject gameMgr = new GameObject("GameManager");
|
||||
gameMgr.AddComponent<TheIsland.Core.GameManager>();
|
||||
Debug.Log("[Setup] Created GameManager");
|
||||
}
|
||||
|
||||
// Create UIManager
|
||||
if (Object.FindFirstObjectByType<TheIsland.UI.UIManager>() == null)
|
||||
{
|
||||
GameObject uiMgr = new GameObject("UIManager");
|
||||
uiMgr.AddComponent<TheIsland.UI.UIManager>();
|
||||
Debug.Log("[Setup] Created UIManager");
|
||||
}
|
||||
|
||||
Debug.Log("[Setup] Managers setup complete!");
|
||||
EditorUtility.DisplayDialog("Managers Setup",
|
||||
"Created/verified:\n" +
|
||||
"- NetworkManager\n" +
|
||||
"- GameManager\n" +
|
||||
"- UIManager\n\n" +
|
||||
"Don't forget to assign AgentPrefab to GameManager!",
|
||||
"OK");
|
||||
}
|
||||
|
||||
[MenuItem("The Island/Documentation")]
|
||||
public static void OpenDocs()
|
||||
{
|
||||
EditorUtility.DisplayDialog("The Island - Quick Guide",
|
||||
"CONTROLS:\n" +
|
||||
"- WASD: Move camera\n" +
|
||||
"- Mouse Scroll: Zoom in/out\n" +
|
||||
"- Click Agent: Feed agent\n\n" +
|
||||
"COMMANDS (in input field):\n" +
|
||||
"- feed Jack/Luna/Bob: Feed agent\n" +
|
||||
"- check: Check status\n" +
|
||||
"- reset: Reset all agents\n\n" +
|
||||
"SETUP ORDER:\n" +
|
||||
"1. The Island > Setup Scene\n" +
|
||||
"2. The Island > Setup Managers\n" +
|
||||
"3. The Island > Create Agent Prefab\n" +
|
||||
"4. Assign prefab to GameManager",
|
||||
"OK");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
2
unity-client/Assets/Editor/AgentPrefabCreator.cs.meta
Normal file
2
unity-client/Assets/Editor/AgentPrefabCreator.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33c77deb1fa6f42bf82baaf575b65c22
|
||||
Reference in New Issue
Block a user