- Home /
Why cant I see the names of my Scripts?
Hi.
I have moved a lot of my scripts into a c# DLL that is in my Assets folder. It opens up just like a folder and I can see most of my scripts there.
Except I cant see those scripts that through inheritance uses generics. Example:
public class StopAnimation : AbstractTriggerableAnimation<string>
{
public override TriggerResult UseAnimation(Animation animation, string animationToUse)
{
if (animation)
{
if (animationToUse.Length > 0)
{
animation.Stop(animationToUse);
}
else
{
animation.Stop();
}
return new TriggerResult();
}
return new TriggerResult(0.0f, false);
}
}
AbstractGenericEntity inherits from MonoBehaviour again, so that is not the problem (ofcourse).
All other scripts that inherits from other abstract classes work. The funny thing is that if I try to add the components via code by using this example:
public override void OnPress(ScriptFile file) { Type scriptType = file.Type; if (scriptType.IsSubclassOf(typeof(MonoBehaviour))) { UnityEngine.Object obj = UnityEngine.Object.FindObjectOfType(scriptType); MonoBehaviour mono = obj as MonoBehaviour;
GameObject go = new GameObject(scriptType.Name);
if (Selection.gameObjects.Length > 0)
{
go = Selection.gameObjects[0];
}
Component comp = go.AddComponent(scriptType);
}
}
... then it appears in the Inspector with no name, but the gameobject that is created gets the correct name. Is this a unity bug? Am I doing something wrong?:
Edit 1: When closing down unity and opening it again, the gameobject in question lists the script as "none" (missing).
Edit 2: Answer to the question below about how I set the type:
private static Directory GetScriptsFromAssembly() { Assembly assembly = Assembly.LoadFrom(name); Directory root = new Directory();
Type[] types = assembly.GetTypes();
length = types.Length;
progress = 0f;
foreach (Type type in types)
{
CheckType(root, type);
}
root.Sort();
return root;
}
This is the complete chain of inheritance with one of the scripts: using UnityEngine; using System.Collections; using EseTriggers;
[EseTriggersMenu("Entity/Behaviour/Animation/Stop Animation")]
public class StopAnimation : AbstractTriggerableAnimation<string>
{
public override TriggerResult UseAnimation(Animation animation, string animationToUse)
{
...
}
}
to
using UnityEngine; using System.Collections; using EseTriggers;
public abstract class AbstractTriggerableAnimation<T> : AbstractGenericEntity<Animation> { public T[] AnimationsToUse = new T[1];
protected override TriggerResult Trigger(Animation component)
{
...
}
public abstract TriggerResult UseAnimation(Animation animation, T animationToUse);
}
to
using UnityEngine; using EseTriggers;
public abstract class AbstractGenericEntity<T> : AbstractEntity { public T[] Targets = new T[1];
protected override TriggerResult OnActivatedByTrigger(object value)
{
...
}
protected abstract TriggerResult Trigger(T target);
}
to
using UnityEngine; using EseTriggers; using System; using System.Linq;
public abstract class AbstractEntity : AbstractConditionableMonobehaviourEntity { public AbstractCondition[] ConditionsToCheck;
public override bool IsConditionMet()
{
...
}
public override void SetCondition(bool isConditionMet)
{
...
}
}
to
using UnityEngine; using EseTriggers; using System;
public abstract class AbstractConditionableMonobehaviourEntity : AbstractConditionableMonoBehaviour, IEntity { public TriggerResult DoActivateTrigger(System.Object value) { ... }
protected abstract TriggerResult OnActivatedByTrigger(object value);
protected bool CanActivateTrigger()
{
...
}
}
to
using EseTriggers; using UnityEngine;
public abstract class AbstractConditionableMonoBehaviour : EseTriggerMonoBehaviour, ICondition {
public abstract bool IsConditionMet();
public abstract void SetCondition(bool isConditionMet);
}
to
using UnityEngine;
public class EseTriggerMonoBehaviour : MonoBehaviour { /// <summary> /// Help text to display for the user setting up the triggers. /// </summary> public string Comment = "";
public float xPosition = 0;
public float XPosition { get { return xPosition; } set { xPosition = value; } }
public float yPosition = 0;
public float YPosition { get { return yPosition; } set { yPosition = value; } }
public virtual void Start()
{
if (!Application.isEditor)
{
Comment = null;
xPosition = 0;
yPosition = 0;
}
}
}
Edit 3: If you have Visual Studio installed then you can take a look at a small test project I uploaded here: http://dl.dropbox.com/u/1972432/Generics_bug.rar
Answer by Statement · Mar 24, 2011 at 08:23 PM
I tried your code, and I can't get it to work with a dll either. I can get it work if I just include the sources right into unity, however dragging out the generic class doesn't work (as expected because we can't define T) but strangely it says the class name doesn't match the file name! I also saw that the generic type in the library had a strange name like MyAwesomeGenericMB`1.
Since Unity is very picky about the file name must match the class name, I am wondering if something similar is happening behind the scenes in your dll import.
Perhaps it won't find MyAwesomeGenericMB < T > because it mangles the name to MyAwesomeGenericMB`1, and so any further subclasses it can't resolve being derived from MonoBehaviour and is rejected. Clearly not ideal in your scenario.
I haven't looked in depth what you're trying to achieve with your inheritance (I must say, it's one of the longest chains I've ever seen!) but perhaps you could either just include the sources into the project or favor composition instead. Users of that library could perhaps declare public fields with your types, that are not derived from monobehaviour but instead use your "custom components" and delegate calls to them? Or make it a bit more specialized and ditch the generics but go with interfaces instead?
Something along the lines such:
public class StopAnimationScript : MonoBehaviour, IStopAnimation { public StopAnimation stopAnimation;
protected virtual void Awake()
{
// Note: StopAnimation shouldn't longer derive from Monobehaviour
// But it can still have generics and inheritance just like you want.
// You should provide all the interface required and delegate the calls
// to the actual implementation. Since we can't make use of generic
// types in a dll, this should probably work out best. Just provide
// building blocks for the user if they want to make customized
// behavior, reusing your classes and building something similar to this.
// But for ease of use, it could be good to provide high level scripts
// so users easily can plug them in without having to write them first.
stopAnimation.host = this;
}
public TriggerResult UseAnimation(Animation animation, string animationToUse)
{
// Delegating call to actual implementation. Provide methods like these
// for all interesting public members you want to access.
return stopAnimation.UseAnimation(animation, animationToUse);
}
}
// You can probably use interfaces for a lot of tasks, and to reduce your great // inheritance chain. public interface IStopAnimation { TriggerResult UseAnimation(Animation animation, string animationToUse); }
I think you are onto something here. +1 for you :)
I came to the same conclusion a couple of days ago and posted it as a bug on their bug tracker but my sources tell me those bugs never gets fixed so I'd be better of just removing the generics from my hierarchy. (Using interfaces wont help me).
Why don't use make a non-generic base class and provide generic methods that act on System.Object ins$$anonymous$$d? Sure, you'd get some boxing with value types (int, float, Vector3 etc) but for reference types ($$anonymous$$onoBehavior, Animation, Light) it's just a simple cast.
That is a good idea, but I have already gone ahead and just made the generic scripts into actual scripts.
Answer by Ullukai · Mar 25, 2011 at 01:09 AM
if it was me with this problem, i would just delete all of it and reinstall unity but first i would make sure the old unity was all erased and also remove the unity folder where it was installed and start again. And of course i would save whatever i wanted to from the old unity folder.
It wouldn't solve the problem. The problem isn't a corrupt installation but rather a limitation in Unity with regard to generic types deriving from $$anonymous$$onoBehaviour in imported libraries.
Your answer
Follow this Question
Related Questions
Expanding the GUI 1 Answer
Generic CustomEditor 1 Answer
Custom property drawer for generic 0 Answers
Mark scenes as 'in modification' or as 'modified' or make a scene unselectable? 0 Answers