Kursach_StealthAction/Assets/Scripts/Editor/CharacterSetup.cs

219 lines
8.6 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
public static class CharacterSetup
{
private const string FbxPath = "Assets/mainhero/balthazar-rigged-animated/source/Balthazar walking/Balthazar walking.Fbx";
private const string ControllerPath = "Assets/mainhero/PlayerAnimator.controller";
private const string MaterialsFolder = "Assets/mainhero/Materials";
[MenuItem("Tools/Setup Main Hero On Player")]
public static string ExecuteSetup()
{
var fbxPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(FbxPath);
if (fbxPrefab == null)
{
Debug.LogError($"[CharacterSetup] FBX model not found at {FbxPath}");
return "FBX model not found!";
}
var controller = AssetDatabase.LoadAssetAtPath<RuntimeAnimatorController>(ControllerPath);
if (controller == null)
{
Debug.LogError($"[CharacterSetup] AnimatorController not found at {ControllerPath}");
return "AnimatorController not found!";
}
// 1. Находим игрока на сцене (Capsule или Player)
GameObject player = GameObject.Find("Capsule");
if (player == null)
{
player = GameObject.Find("Player");
}
if (player == null)
{
// Попробуем найти через PlayerMovement
var pmFound = Object.FindAnyObjectByType<PlayerMovement>();
if (pmFound != null) player = pmFound.gameObject;
}
if (player == null)
{
return "Player / Capsule GameObject not found in scene!";
}
Undo.RegisterFullObjectHierarchyUndo(player, "Setup Main Hero Character");
// 2. Переименовываем в Player для порядка
player.name = "Player";
// 3. Отключаем визуальный меш капсулы
var meshRenderer = player.GetComponent<MeshRenderer>();
if (meshRenderer != null)
{
meshRenderer.enabled = false;
}
// Отключаем лишний CapsuleCollider, так как CharacterController сам является коллайдером
var capCol = player.GetComponent<CapsuleCollider>();
if (capCol != null)
{
capCol.enabled = false;
}
// 4. Проверяем наличие дочерней модели, удаляем старую при повторном запуске
Transform oldModel = player.transform.Find("Model");
if (oldModel != null)
{
Object.DestroyImmediate(oldModel.gameObject);
}
// 5. Создаем экземпляр модели из FBX как дочерний объект
GameObject modelGo = (GameObject)PrefabUtility.InstantiatePrefab(fbxPrefab, player.transform);
modelGo.name = "Model";
modelGo.transform.localPosition = new Vector3(0f, -1f, 0f); // Смещаем вниз к основанию CharacterController
modelGo.transform.localRotation = Quaternion.identity;
modelGo.transform.localScale = Vector3.one;
// 6. Подгружаем материалы из папки Materials
var matDict = new Dictionary<string, Material>();
string[] matGuids = AssetDatabase.FindAssets("t:Material", new[] { MaterialsFolder });
foreach (var guid in matGuids)
{
string p = AssetDatabase.GUIDToAssetPath(guid);
var m = AssetDatabase.LoadAssetAtPath<Material>(p);
if (m != null)
{
matDict[m.name] = m;
}
}
// Назначаем материалы всем рендерам модели
var renderers = modelGo.GetComponentsInChildren<SkinnedMeshRenderer>(true);
foreach (var r in renderers)
{
var mats = r.sharedMaterials;
for (int i = 0; i < mats.Length; i++)
{
if (mats[i] != null && matDict.TryGetValue(mats[i].name, out var foundMat))
{
mats[i] = foundMat;
}
}
r.sharedMaterials = mats;
}
// 7. Настраиваем Animator
var animator = modelGo.GetComponent<Animator>();
if (animator == null)
{
animator = modelGo.AddComponent<Animator>();
}
// Подгружаем Humanoid Avatar модели
var subAssets = AssetDatabase.LoadAllAssetsAtPath(FbxPath);
foreach (var a in subAssets)
{
if (a is Avatar av)
{
animator.avatar = av;
break;
}
}
animator.runtimeAnimatorController = controller;
animator.applyRootMotion = false; // Движением управляет CharacterController
// 8. Привязываем аниматор к PlayerMovement, PlayerAttack и PlayerGun
var pm = player.GetComponent<PlayerMovement>();
if (pm != null)
{
pm.animator = animator;
EditorUtility.SetDirty(pm);
}
var pa = player.GetComponent<PlayerAttack>();
if (pa != null)
{
pa.animator = animator;
EditorUtility.SetDirty(pa);
}
var pg = player.GetComponent<PlayerGun>();
if (pg != null)
{
pg.playerAnimator = animator;
EditorUtility.SetDirty(pg);
}
var echo = player.GetComponent<EchoTrigger>();
if (echo != null)
{
echo.playerAnimator = animator;
echo.FindFootBones();
EditorUtility.SetDirty(echo);
}
// 9. Проверяем CameraFollow на главной камере
if (Camera.main != null)
{
var camFollow = Camera.main.GetComponent<CameraFollow>();
if (camFollow != null)
{
camFollow.target = player.transform;
EditorUtility.SetDirty(camFollow);
}
}
// 10. Находим кость правой руки для оружия
Transform rHand = animator.GetBoneTransform(HumanBodyBones.RightHand);
Transform gunHolder = rHand != null ? rHand.Find("GunHolder") : null;
if (gunHolder == null) gunHolder = player.transform.Find("GunHolder");
if (gunHolder != null && rHand != null && gunHolder.parent != rHand)
{
gunHolder.SetParent(rHand, false);
gunHolder.localPosition = new Vector3(0.08f, 0.04f, -0.02f);
gunHolder.localRotation = Quaternion.Euler(279.58f, 351.41f, 180.18f);
}
if (gunHolder != null && gunHolder.Find("M1911 Handgun_Black") == null)
{
for (int i = gunHolder.childCount - 1; i >= 0; i--)
{
Object.DestroyImmediate(gunHolder.GetChild(i).gameObject);
}
var gunPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Nokobot/Modern Guns - Handgun/_Prefabs/Handgun Black/M1911 Handgun_Black.prefab");
if (gunPrefab != null)
{
var gunInst = (GameObject)PrefabUtility.InstantiatePrefab(gunPrefab, gunHolder);
gunInst.name = "M1911 Handgun_Black";
gunInst.transform.localPosition = Vector3.zero;
gunInst.transform.localRotation = Quaternion.identity;
if (pg != null)
{
Transform barrel = gunInst.transform.Find("Barrel_Location");
Transform modelM = gunInst.transform.Find("M1911 Handgun_Model");
pg.muzzlePoint = barrel;
pg.gunAnimator = modelM != null ? modelM.GetComponent<Animator>() : null;
pg.casingExitPoint = modelM != null ? modelM.Find("CasingExit") : null;
pg.gunModelTransform = gunHolder;
pg.muzzleFlashPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Nokobot/Modern Guns - Handgun/Effects/MuzzleFlash.prefab");
pg.casingPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Nokobot/Modern Guns - Handgun/_Prefabs/45ACP Bullet_Casing.prefab");
EditorUtility.SetDirty(pg);
}
}
}
EditorSceneManager.MarkSceneDirty(player.scene);
EditorSceneManager.SaveScene(player.scene);
Debug.Log("[CharacterSetup] Main hero character successfully configured on Player!");
return "SUCCESS: Main hero character successfully configured on Player!";
}
}