using UnityEngine; using UnityEngine.UI; using UnityEditor; using UnityEditor.Animations; public class PlayerBuilderTool : EditorWindow { // Модель private GameObject characterModel; private Transform headBone; // Параметры движения private float walkSpeed = 5f; private float runSpeed = 9f; private float crouchSpeed = 2.5f; private float jumpHeight = 1.5f; private float gravity = -9.81f; // Коллайдер private float height = 1.8f; private float radius = 0.5f; private float centerY = 0.9f; // Камера private bool addCamera = true; private float cameraHeight = 1.7f; // Анимации private AnimationClip idleClip; private AnimationClip walkClip; private AnimationClip runClip; private AnimationClip jumpClip; private AnimationClip crouchIdleClip; private AnimationClip crouchWalkClip; // Аниматор контроллер private AnimatorController animatorController; private bool createAnimatorController = true; [MenuItem("Tools/Player Builder")] public static void ShowWindow() { GetWindow("Конструктор Персонажа"); } void OnGUI() { GUILayout.Label("Настройки персонажа", EditorStyles.boldLabel); // Секция модели GUILayout.Label("Модель", EditorStyles.miniBoldLabel); characterModel = (GameObject)EditorGUILayout.ObjectField("Модель персонажа", characterModel, typeof(GameObject), false); headBone = (Transform)EditorGUILayout.ObjectField("Кость головы", headBone, typeof(Transform), true); GUILayout.Space(10); // Секция движения GUILayout.Label("Движение", EditorStyles.miniBoldLabel); walkSpeed = EditorGUILayout.FloatField("Скорость ходьбы", walkSpeed); runSpeed = EditorGUILayout.FloatField("Скорость бега", runSpeed); crouchSpeed = EditorGUILayout.FloatField("Скорость краулинга", crouchSpeed); jumpHeight = EditorGUILayout.FloatField("Высота прыжка", jumpHeight); gravity = EditorGUILayout.FloatField("Гравитация", gravity); GUILayout.Space(10); // Секция коллайдера GUILayout.Label("Коллайдер", EditorStyles.miniBoldLabel); height = EditorGUILayout.FloatField("Высота", height); radius = EditorGUILayout.FloatField("Радиус", radius); centerY = EditorGUILayout.FloatField("Центр Y", centerY); GUILayout.Space(10); // Секция камеры GUILayout.Label("Камера", EditorStyles.miniBoldLabel); addCamera = EditorGUILayout.Toggle("Добавить камеру", addCamera); if (addCamera) { cameraHeight = EditorGUILayout.Slider("Высота камеры", cameraHeight, 1f, 2f); } GUILayout.Space(10); // Секция анимаций GUILayout.Label("Анимации", EditorStyles.miniBoldLabel); createAnimatorController = EditorGUILayout.Toggle("Создать контроллер", createAnimatorController); idleClip = (AnimationClip)EditorGUILayout.ObjectField("Idle", idleClip, typeof(AnimationClip), false); walkClip = (AnimationClip)EditorGUILayout.ObjectField("Walk", walkClip, typeof(AnimationClip), false); runClip = (AnimationClip)EditorGUILayout.ObjectField("Run", runClip, typeof(AnimationClip), false); jumpClip = (AnimationClip)EditorGUILayout.ObjectField("Jump", jumpClip, typeof(AnimationClip), false); crouchIdleClip = (AnimationClip)EditorGUILayout.ObjectField("Crouch Idle", crouchIdleClip, typeof(AnimationClip), false); crouchWalkClip = (AnimationClip)EditorGUILayout.ObjectField("Crouch Walk", crouchWalkClip, typeof(AnimationClip), false); if (characterModel != null) { var animator = characterModel.GetComponent(); if (animator != null && animator.avatar != null) { EditorGUILayout.HelpBox("Модель содержит Animator - аватар будет скопирован", MessageType.Info); } } GUILayout.Space(20); // Кнопки действий GUI.color = Color.green; if (GUILayout.Button("Создать в сцене")) { BuildPlayer("Player"); } GUI.color = Color.cyan; if (GUILayout.Button("Сохранить как префаб")) { SaveAsPrefab(); } GUI.color = Color.yellow; if (GUILayout.Button("Создать с тестовой моделью (капсула)")) { BuildTestPlayer(); } GUI.color = Color.white; GUILayout.Space(10); EditorGUILayout.HelpBox( "1. Назначьте модель персонажа\n" + "2. Назначьте анимации (опционально)\n" + "3. Настройте параметры\n" + "4. Нажмите 'Создать в сцене'", MessageType.Info); } void BuildPlayer(string playerName) { GameObject player = new GameObject(playerName); // CharacterController var cc = player.AddComponent(); cc.height = height; cc.radius = radius; cc.center = new Vector3(0, centerY, 0); // Скрипт персонажа var character = player.AddComponent(); character.walkSpeed = walkSpeed; character.runSpeed = runSpeed; character.crouchSpeed = crouchSpeed; character.jumpHeight = jumpHeight; character.gravity = gravity; // Модель GameObject model = null; if (characterModel != null) { model = Instantiate(characterModel, player.transform); model.transform.localPosition = Vector3.zero; model.transform.localRotation = Quaternion.identity; // Голова if (headBone != null) { character.head = headBone; } else { character.head = FindChildBone(model.transform, "Head"); } //Animator var modelAnimator = model.GetComponent(); if (modelAnimator != null && modelAnimator.avatar != null) { var animator = player.AddComponent(); animator.avatar = modelAnimator.avatar; } } // Голова если не найдена if (character.head == null) { GameObject headObj = new GameObject("HeadPoint"); headObj.transform.SetParent(model != null ? model.transform : player.transform); headObj.transform.localPosition = new Vector3(0, height - 0.2f, 0); character.head = headObj.transform; } // Камера if (addCamera && character.head != null) { GameObject cameraObj = new GameObject("PlayerCamera"); cameraObj.transform.SetParent(character.head); cameraObj.transform.localPosition = new Vector3(0, 0.1f, 0); var cam = cameraObj.AddComponent(); cam.tag = "MainCamera"; cam.nearClipPlane = 0.1f; // Удалить старую var oldCam = GameObject.FindWithTag("MainCamera"); if (oldCam != null && oldCam != cameraObj) { DestroyImmediate(oldCam); } } // Тег player.tag = "Player"; // Позиция player.transform.position = new Vector3(0, 2, -5); Selection.activeGameObject = player; Debug.Log($"[PlayerBuilder] Создан: {playerName}"); } void SaveAsPrefab() { string path = EditorUtility.SaveFilePanelInProject( "Сохранить префаб", "Player", "prefab", "Выберите место"); if (string.IsNullOrEmpty(path)) return; BuildPlayer("PlayerTemp"); GameObject player = GameObject.Find("PlayerTemp"); if (player == null) { Debug.LogError("Не удалось создать игрока"); return; } GameObject prefab = PrefabUtility.SaveAsPrefabAsset(player, path); DestroyImmediate(player); Selection.activeObject = prefab; Debug.Log($"[PlayerBuilder] Сохранено: {path}"); } void BuildTestPlayer() { characterModel = null; headBone = null; BuildPlayer("TestPlayer"); GameObject player = Selection.activeGameObject; if (player == null) return; // Создаём визуальную часть GameObject body = GameObject.CreatePrimitive(PrimitiveType.Capsule); body.name = "Body"; body.transform.SetParent(player.transform); body.transform.localPosition = Vector3.zero; DestroyImmediate(body.GetComponent()); GameObject head = new GameObject("Head"); head.transform.SetParent(player.transform); head.transform.localPosition = new Vector3(0, centerY + 0.2f, 0); var character = player.GetComponent(); if (character != null) { character.head = head.transform; } if (addCamera) { GameObject camObj = new GameObject("PlayerCamera"); camObj.transform.SetParent(head.transform); camObj.transform.localPosition = new Vector3(0, 0.1f, 0); var cam = camObj.AddComponent(); cam.tag = "MainCamera"; var oldCam = GameObject.FindWithTag("MainCamera"); if (oldCam != null && oldCam != camObj) { DestroyImmediate(oldCam); } } Debug.Log("[PlayerBuilder] Создан тестовый игрок"); } Transform FindChildBone(Transform parent, string boneName) { if (parent == null) return null; if (parent.name.ToLower().Contains(boneName.ToLower())) return parent; foreach (Transform child in parent) { var result = FindChildBone(child, boneName); if (result != null) return result; } return null; } }