【问题标题】:Unity3D Custom Inspector resets variable every frameUnity3D 自定义检查器每帧重置变量
【发布时间】:2018-02-21 02:07:09
【问题描述】:

我对自定义检查器/编辑器非常陌生,这让我很困扰。我在下面有自定义编辑器脚本来设置我的船对象(太空船,而不是海船)。问题是,每次我将控制类型设置为 AI 时,它只停留一帧,然后将自身重置为 Player(默认值)。如前所述,自定义编辑器非常新,不知道出了什么问题。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;


[CustomEditor(typeof(Ship))]
public class ShipInspector : Editor
{
    enum Controlled
    {
        Player = 0,
        AI = 1,
    }
    Ai shipAi;
    Ship ship;
    Controlled actualControll = Controlled.Player;
    public override void OnInspectorGUI()
    {
        ship = (Ship)target;
        shipAi = ship.gameObject.GetComponent<Ai>();
        actualControll = ((Controlled)EditorGUILayout.EnumPopup("Controll Type", actualControll));
        if (actualControll == Controlled.Player)
        {
            ship.isPlayer = true;
            if (shipAi != null)
            {
                DestroyAi();
            }
        }
        else if (actualControll == Controlled.AI)
        {
            ship.isPlayer = false;
            if (shipAi == null)
            {
                CreateAi();
            }
        }
        EditorGUILayout.Separator();
        EditorGUILayout.LabelField("General Setup");
        ship.maxHull = EditorGUILayout.IntField("Maximal Hull", ship.maxHull);
        ship.maxShields = 0;
        ship.maxEnergi = EditorGUILayout.IntField("Maximal battery", ship.maxEnergi);
        ship.energiRegenRate = EditorGUILayout.FloatField("Energi regen cooldown", ship.energiRegenRate);
        EditorGUILayout.Separator();
        EditorGUILayout.LabelField("Weapon setup");
        EditorGUILayout.LabelField("For positions : X, Y and Z are coordinates relative to");
        EditorGUILayout.LabelField("ship's center, H is angle rotation around ship's center");
        EditorGUILayout.PropertyField(serializedObject.FindProperty("primWeaponsPos"), true);
        EditorGUILayout.PropertyField(serializedObject.FindProperty("secWaponsPos"), true);
        serializedObject.ApplyModifiedProperties();
    }
    public void CreateAi()
    {
        shipAi = (Ai)ship.gameObject.AddComponent(typeof(Ai));
        shipAi.ship = ship;
    }
    public void DestroyAi()
    {
        DestroyImmediate(shipAi, false);
        shipAi = null;
    }
}
这是船级

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Ship : Targetable
{
    public Vector3 camPos = new Vector3(0, -10, -30);
    public Vector3 lightPos;
    public ParticleSystem[] enginesParticles;
    public ParticleSystem[] reverseEngineParticles;
    public Vector4[] primWeaponsPos;
    public Vector4[] secWaponsPos;
    public List<PrimarWeaponController> primWeapons = new List<PrimarWeaponController>();
    public List<SecundarWeaponController> secWeapons = new List<SecundarWeaponController>();
    public EngineController engine;
    AddonController addon;
    public Animator anim;
    public Rigidbody2D rb;
    public Targetable target;
    public float massModifier;
    public float energiRegenRate;
    public bool isPlayer;
    public float breakDistance;
    Ai ai;
    /// <summary>
    /// Weapons will be set as childs of this object.
    /// </summary>
    public Transform weaponBone;
    void Start()
    {
        camPos = new Vector3(0, -10, -30);
        InitializeEqipment(0, 0, 0, 0, -1);
        rb = gameObject.GetComponent<Rigidbody2D>();
        if (isPlayer == true)
        {
            Instantiate(Resources.Load("Light2", typeof(GameObject)) as GameObject, PublicFunctions.RotateAroundPoint2D(transform.position + lightPos, transform.position, transform.rotation.eulerAngles.z), Quaternion.Euler(-90, 0, transform.rotation.eulerAngles.z)).transform.SetParent(this.gameObject.transform, true);
        }
        hull = maxHull;
        shields = 0;
        energi = maxEnergi;
        base.ColorTheDot();
        Invoke("RegenEnergi", energiRegenRate);
        if (isPlayer == false)
        {
            ai = GetComponent<Ai>();
            ai.ship = gameObject.GetComponent<Ship>();
            ai.InicializeAI();
        }
    }

    void Update()
    {
        float t = ((rb.velocity.magnitude) / engine.maximalSpeed) / engine.speedGain * Time.deltaTime;
        breakDistance = (rb.velocity.sqrMagnitude) * t + (((engine.speedGain * t) * (engine.speedGain * t)) / 2);
        if (energi > maxEnergi) { energi = maxEnergi; } else if (energi < 0) { energi = 0; }
        if (isPlayer == true)
        {
            Camera.main.transform.position = PublicFunctions.RotateAroundPoint2D(transform.position + camPos, transform.position, transform.rotation.eulerAngles.z - 180f);
            Camera.main.transform.rotation = Quaternion.Euler(0, 0, transform.rotation.eulerAngles.z);
            engine.Rotate(-Input.GetAxis("Mouse X"));
        }
        if (Input.GetKeyDown(DataManager.cof.targetFront) && isPlayer == true)
        {
            RaycastHit2D[] hits = Physics2D.RaycastAll(transform.position, transform.TransformDirection(Vector3.up));
            foreach (RaycastHit2D hit in hits)
            {
                if (hit.collider.gameObject != this.gameObject)
                {
                    Targetable tar = hit.collider.gameObject.GetComponent<Targetable>();
                    if (tar != null)
                    {
                        if (tar.faction != faction)
                        {
                            if (Vector3.Distance(transform.position, tar.gameObject.transform.position) <= 70f)
                            {
                                target = tar;
                                GameObject inst = Instantiate(Resources.Load("UI/RadarPointer", typeof(GameObject)) as GameObject, Vector3.zero, Quaternion.Euler(0f, 0f, 0f));
                                inst.transform.SetParent(GameObject.Find("Hud/Radar").transform);
                                RadarPointer rp = inst.GetComponent<RadarPointer>();
                                rp.actualType = RadarPointer.radarType.TargetedEnemy;
                                rp.target = target.gameObject;
                                break;
                            }
                        }
                    }
                }
            }
        }
        if (Input.GetKey(DataManager.cof.usePrimWeapon) && isPlayer == true)
        {
            foreach (PrimarWeaponController p in primWeapons)
            {
                p.Use();
            }
        }
        if (Input.GetKey(DataManager.cof.useSecWeapon) && isPlayer == true)
        {
            foreach (SecundarWeaponController s in secWeapons)
            {
                s.Use();
            }
        }
        if (Input.GetKeyDown(DataManager.cof.thrust) && isPlayer == true)
        {
            engine.ThrustUp();
        }
        if (Input.GetKeyUp(DataManager.cof.thrust) && isPlayer == true)
        {
            engine.ThrustDown();
        }
        if (Input.GetKeyDown(DataManager.cof.back) && isPlayer == true)
        {
            engine.ReverseUp();
        }
        if (Input.GetKeyUp(DataManager.cof.back) && isPlayer == true)
        {
            engine.ReverseDown();
        }
        if (Input.GetKey(DataManager.cof.useAddon) && isPlayer == true)
        {
            addon.Use();
        }
        if (isPlayer == false)
        {
            ai.Lock();
            ai.Attack();
            ai.Move();

        }
    }
    void RegenEnergi()
    {
        energi = energi + 1;
        Invoke("RegenEnergi", energiRegenRate);
    }
    void OnDrawGizmos()
    {
        Gizmos.color = Color.white;
        Gizmos.DrawIcon(PublicFunctions.RotateAroundPoint2D(transform.position + lightPos, transform.position, transform.rotation.eulerAngles.z), "LightIcon");
        Gizmos.DrawCube(PublicFunctions.RotateAroundPoint2D(camPos, transform.position, transform.rotation.eulerAngles.z - 180f), Vector3.one);
        if (primWeaponsPos.Length > 0)
        {
            foreach (Vector4 v4 in primWeaponsPos)
            {
                Gizmos.DrawIcon(PublicFunctions.RotateAroundPoint2D(new Vector3(v4.x, v4.y, v4.z) + transform.position, transform.position, transform.rotation.eulerAngles.z + v4.w), "PrimWeaponIcon", true);
            }
        }
        if (secWaponsPos.Length > 0)
        {
            foreach (Vector4 v4 in secWaponsPos)
            {
                Gizmos.DrawIcon(PublicFunctions.RotateAroundPoint2D(new Vector3(v4.x, v4.y, v4.z) + transform.position, transform.position, transform.rotation.eulerAngles.z + v4.w), "SecWeaponIcon", true);
            }
        }
        Gizmos.color = Color.red;
        Gizmos.DrawRay(transform.position, transform.TransformDirection(Vector3.up * breakDistance));
    }
    void InitializeEqipment(int gunId, int secId, int engId, int shldId, int addonId)
    {
        if (gunId != -1)
        {
            foreach (Vector4 pos in primWeaponsPos)
            {
                GameObject inst = Instantiate(Database.guns[gunId].gObject, PublicFunctions.RotateAroundPoint2D((Vector3)pos + transform.position, transform.position, transform.rotation.eulerAngles.z + pos.w), transform.rotation);
                PrimarWeaponController prim = inst.GetComponent<PrimarWeaponController>();
                prim.damage = Database.guns[gunId].damage;
                prim.cooldown = Database.guns[gunId].cooldown;
                prim.capacity = Database.guns[gunId].capacity;
                prim.projectile = Database.guns[gunId].projectile;
                prim.projectileSpeed = Database.guns[gunId].maximalSpeed;
                prim.GunsCount = primWeaponsPos.Length;
                prim.ship = GetComponent<Ship>();
                inst.transform.SetParent(weaponBone);
                primWeapons.Add(inst.GetComponent<PrimarWeaponController>());
                if (isPlayer == true)
                {
                    GameObject.Find("Hud/Top_Left/PrimSkill").GetComponent<SkillIcon>().noSkill = false;
                    GameObject.Find("Hud/Top_Left/PrimSkill").GetComponent<SkillIcon>().UpdateIcon();
                    GameObject.Find("Hud/Top_Left/PrimSkill").GetComponent<SkillIcon>().gunClass = Database.guns[gunId].thisType;
                }
            }
        }
        else
        {
            if (isPlayer == true)
            {
                GameObject.Find("Hud/Top_Left/PrimSkill").GetComponent<SkillIcon>().nullSkill();
            }
        }
        if (secId != -1)
        {
            foreach (Vector4 pos in secWaponsPos)
            {
                GameObject inst = Instantiate(Database.rockets[secId].gObject, PublicFunctions.RotateAroundPoint2D((Vector3)pos + transform.position, transform.position, transform.rotation.eulerAngles.z + pos.w), transform.rotation);
                SecundarWeaponController sec = inst.GetComponent<SecundarWeaponController>();
                sec.damage = Database.rockets[secId].damage;
                sec.cooldown = Database.rockets[secId].cooldown;
                sec.speedGain = Database.rockets[secId].speedGain;
                sec.maximalSpeed = Database.rockets[secId].maximalSpeed;
                sec.count = Database.rockets[secId].capacity;
                sec.turnRate = Database.rockets[secId].turnRate;
                sec.type = Database.rockets[secId].thisRocket;
                sec.projectile = Database.rockets[secId].projectile;
                sec.ship = GetComponent<Ship>();
                if (isPlayer == true)
                {
                    GameObject.Find("Hud/Top_Left/SecSkill").GetComponent<SkillIcon>().noSkill = false;
                    GameObject.Find("Hud/Top_Left/SecSkill").GetComponent<SkillIcon>().UpdateIcon();
                    GameObject.Find("Hud/Top_Left/SecSkill").GetComponent<SkillIcon>().rocketType = Database.rockets[secId].thisRocket;
                    GameObject.Find("Hud/Top_Left/SecSkill").GetComponent<SkillIcon>().useAmmo = true;
                    GameObject.Find("Hud/Top_Left/SecSkill").GetComponent<SkillIcon>().count = Database.rockets[secId].capacity;
                }
                inst.transform.SetParent(weaponBone);
                secWeapons.Add(inst.GetComponent<SecundarWeaponController>());
            }
        }
        else
        {
            GameObject.Find("Hud/Top_Left/SecSkill").GetComponent<SkillIcon>().nullSkill();
        }
        EngineController eng = gameObject.AddComponent(typeof(EngineController)) as EngineController;
        eng.speedGain = Database.engines[engId].speedGain;
        eng.turnRate = Database.engines[engId].turnRate;
        eng.maximalSpeed = Database.engines[engId].maximalSpeed;
        engine = eng;
        if (shldId != -1)
        {
            ShieldController shld = gameObject.AddComponent(typeof(ShieldController)) as ShieldController;
            shld.capacity = Database.shields[shldId].capacity;
            shld.regenRate = Database.shields[shldId].speedGain;
            shld.ship = gameObject.GetComponent<Ship>();
        }
        if (addonId != -1)
        {
            AddonController add = gameObject.AddComponent(typeof(AddonController)) as AddonController;
            add.cooldown = Database.addons[addonId].cooldown;
            add.maximalAmmo = Database.addons[addonId].capacity;
            if (isPlayer == true)
            {
                GameObject.Find("Hud/Top_Left/AddonSkill").GetComponent<SkillIcon>().noSkill = false;
                GameObject.Find("Hud/Top_Left/AddonSkill").GetComponent<SkillIcon>().UpdateIcon();
                GameObject.Find("Hud/Top_Left/AddonSkill").GetComponent<SkillIcon>().addonId = addonId;
            }
            addon = add;
        }
        else
        {
            if (isPlayer == true)
            {
                GameObject.Find("Hud/Top_Left/AddonSkill").GetComponent<SkillIcon>().nullSkill();
            }
        }
    }
}

【问题讨论】:

  • 同时显示您的Ship 课程。
  • @Draco18s 当然,我编辑了我的问题。

标签: c# unity3d


【解决方案1】:

Inspector 脚本字段未序列化。

这个属性:

Controlled actualControll

与您的其他字段不同,不是从您的 Ship 对象填充的。这个值是这样的:

Controlled actualControll = Controlled.Player;
// ...
actualControll = ((Controlled)EditorGUILayout.EnumPopup("Controll Type", actualControll));

您的检查器脚本无法确定该值是否为Controlled.Player 以外的任何值,即使您从下拉列表中选择了一个新值,当该对象刷新检查器时(每次发生任何变化时都会发生这种情况) 值首先设置为 Player,然后从下拉列表中查询(默认值 = Player),然后根据该值执行操作(提示:它是 Player)。你的Ship 类不知道是谁控制它。

嗯,它通过ship.isPlayer 进行,但该值由下拉列表中的值驱动,但下拉列表中的值并非同样由船本身所驱动设置。 你覆盖每一帧的值。

试试这个:

actualControll = ((Controlled)EditorGUILayout.EnumPopup(
    "Controll Type", ship.isPlayer ? Controlled.Player : Controlled.AI));

【讨论】:

  • 所以,如果我理解正确的话,仅检查员的值不会被维护,并且仅因为它们没有序列化而恢复为默认值?
  • @Garrom 是的。
  • 可以是任何类吗?即使是静态的?还是必须检查类?
  • 只要将其存储在其他地方就可以了。我自己并没有测试所有这些选项,只制作了一两个编辑器脚本。
猜你喜欢
  • 1970-01-01
  • 2015-03-15
  • 1970-01-01
  • 2017-04-03
  • 2018-05-26
  • 2019-10-18
  • 2018-05-21
  • 2020-07-02
  • 2016-09-14
相关资源
最近更新 更多