Function with vector parameter not shown in OnDelta Editor // Unity 2019.2.6f1 - unity3d

I´m using the Lean Touch+ Asset to implement drag and drop for 3D objects. Unfortunately the needed function is not showing up in the OnDelta() event editor.
The example is working, but showing in the event editor. Also I tried an older 2018 unity version and there it works fine. Anyway I´d like to use the newer one.
If I change the Vector2 to a float, it gets listed in the editor, but Vector2 should work as well or am I wrong?
This code is not complete, because it´s not mine and I´m not sure if I can just share it. But I hope it helps understanding my problem.
using UnityEngine;
namespace Lean.Touch
{
[HelpURL(LeanTouch.PlusHelpUrlPrefix + "LeanManualTranslate")]
[AddComponentMenu(LeanTouch.ComponentPathPrefix + "Manual Translate")]
public class LeanManualTranslate : MonoBehaviour
{
public void TranslateAB(Vector2 magnitude)
{
Translate(DirectionA * magnitude.x + DirectionB * magnitude.y);
}

There are basically two types of callbacks for UnityEvent
Static
Static calls are preconfigured calls, with preconfigured values that are set in the UI. This means that when the callback is invoked, the target function is invoked with the argument that has been entered into the UI.
Dynamic
Dynamic calls are invoked using an argument that is sent from code, and this is bound to the type of UnityEvent that is being invoked. The UI filters the callbacks and only shows the dynamic calls that are valid for the UnityEvent.
UI refers to the Inspector in the Unty Editor here.
BUT .. unfortunately there is a Bug in newer versions so dynamic parameters do not work with UnityEvent currently.
(Fixed in 2019.3 and 2020.1 ... don't use those though as the are still in Alpha & Beta state!)
In general Vector2 was afaik never a parameter to be displayed and edited via the Inspector when choosing a static callback type and was only applicable for passing it to a dynamic callback.
Only the basic types like int, string, float, bool and Object references work for the static ones.
As a workaround you can still add callbacks on runtime via script - though it is kind of shitty and only makes sense if the target component sits on the same GameObject as the one with the UnityEvent
public class LeanManualTranslate : MonoBehaviour
{
private void Awake()
{
GetComponent<LeanMultiSet>().OnDelta.AddCallback(TranslateAB);
}
private void TranslateAB(Vector2 magnitude)
{
Translate(DirectionA * magnitude.x + DirectionB * magnitude.y);
}
}
Or alternatively stick with 2019.1.14 where it works as well. There bug seems to be introduced since 2019.2

Related

How to bake or compute my script data before play

So, I am working on a unity project that involves a lot of math. It takes about 1-2 seconds for the math to finish on start.
Is there any way to "bake" or "compute" this data before the game starts. I saw something similar done in this script from this project. My project has nothing to do with this script, it is just an example.
I would prefer not to share my code. I need to compute the variables from a method called Initialize()
I fixed this by using [SerializeField, HideInInspector] before the variables I wanted to bake.
Then I would create a new class (can be in the same script). You have to using UnityEditor then your class should be something like
[CustomEditor(typeof(classToBake))]
public class BakeGUI : Editor
{
}
Call function override public void OnInspectorGUI() then call functions of the type EditorGUILayout Then you have to create a variable of the type of script.
using UnityEditor;
[CustomEditor(typeof(classToBake))]
public class BakeGUI: Editor
{
override public void OnInspectorGUI()
{
classToBake bake = (classToBake)target;
if (GUILayout.Button("Compile Data"))
{
bake.Compile();
}
if (GUILayout.Button("Delete Data"))
{
bake.ResetData();
}
DrawDefaultInspector();
}
}
Finally, how to use this.
change classtoBake to the script with the data you want to bake
In the if statements, you can run methods when they click the buttons.
The most important thing
After you have this working, to save your data, YOU MUST have the variables you are going to change have the attributes [SerializeField, HideInInspector]

Can't drag scene object onto public UnityEvent

I have a script with a public UnityEvent and I am trying to drag a scene object to the object slot so I can access its methods but its not accepting the object. I'm not sure what i'm doing wrong.
The scene object is a prefab instance and I did try unpacking the prefab but it didnt make a difference.
In a comment you mentioned the script you are talking about is a StateMachineBehaviour.
StateMachineBehaviour does not inherit from MonoBehaviour but rather from ScriptableObject
ScriptableObject instances "live" in the Assets not a certain Scene
You (usually) can not have any Scene references in any assets like Prefabs or ScriptableObjects.
There are some workarounds however that still allow you to do that. You can e.g. create ScriptableObject containers for every value you want to pass. Something like e.g.
[CreateAssetMenu]
public class GameObjectReference : ScriptableObject
{
public GameObject gameObject;
public void SetActive(bool value)
{
if(gameObject) gameObject.SetActive(value);
}
}
such an instance of GameObjectReference now is a ScriptableObject and thus also "lives" in the Assets => you can reference it in any other asset as Prefabs and other ScriptableObjects.
So all you need to do is make sure that you set this value from within your scene e.g. using
[ExecuteInEditMode]
public class GameObjectReferenceSetter : MonoBehaviour
{
public GameObjectReference gameObjectReferenceAsset;
private void Awake()
{
gameObjectReferenceAsset.gameObject = gameObject;
}
}
You can create such a reference-asset and setter pair for each type you need and transpass the required public methods so you can call them from the UnityEvent.
Having the [ExecuteInEditMode] this should also be set already in EditMode. However since "officially" it is still not possible to have a scene reference on a ScriptableObject field the value usually says Type missmatch but references the correct object as you should see when you click on the field.
Another alternative is using some kind of dependency-injection (for Unity an often mentioned and free solution is e.g. Zenject). It is a bit complex to set it up the first time but once you got it working it is more flexible and better scaleable since you wouldn't need to implement a wrapper for each type you want to pass in to a StateMachineBehaviour.
More information and how-tos about Zenject can be found on their github page

'new' operator log warning when creating a GameObject, how to get around it?

Im wondering about something I am doing that is causing this well known warning:
You are trying to create a MonoBehaviour using the 'new' keyword. This is not allowed. MonoBehaviours can only be added using AddComponent(). Alternatively, your script can inherit from ScriptableObject or no base class at all.
I know that I can simply use the Addcomponent<T> to avoid that logwarning. I also understand that unity does not allow anything inheriting from monobehaviour to be instantiated (ref).
It should be said however that right now the tests providing this logwarning are all working fine, I just want to get rid of the warning.
This is an example of a test that gives this error.
[Test]
public void HandleHoverSetsCurrentInteractableOnInteractor()
{
/// Arrange
GameObject actor;
actor = new GameObject();
actor.AddComponent<XRController>();
GameObject actable;
actable = new GameObject();
Handle h = actable.AddComponent<Handle>();
h.Hover(actor.GetComponent<IActor>());
/// Assert
Assert.IsNotNull(actor.GetComponent<IActor>().currentInteractable);
}
Now as mentioned earlier this works exactly as I would expect and it is creating the GameObject and testing the Hover functionality. It's just giving me that logwarning every time I do this. I am therefore wondering if there is a correct way of doing this? preferably without the logwarning.

Is it a good practice to create a class between my own scripts and mono behavior?

So, I have bound the CombatController to an object called "godObject". In the Start() method, I call init() functions on other classes. I did this so I can control the order in which objects are initialized since, for example, the character controller relies on the grid controller being initialized.
Quick diagram:
-------------------- calls
| CombatController | ----------> CameraController.init();
-------------------- |
| ---> GridController.init();
|
| ---> CharacterController.init();
So, now I have a slight problem. I have multiple properties that I need in every controller. At the moment, I have bound everything to the combat controller itself. That means that, in every controller, I have to get an instance of the CombatController via GameObject.Find("godObject).GetComponent<CombatController>(). To be honest, I don't think this is good design.
My idea now was to create a BaseCombatController that extends MonoBehavior, and then have all other classes like GridController, CharacterController etc. extend the BaseCombatController. It might look like this:
public class BaseCombatController : MonoBehaviour
{
public GameObject activePlayer;
public void setActivePlayer(GameObject player) {
this.activePlayer = player;
}
... more stuff to come ...
}
This way, I could access activePlayer everywhere without the need to create a new instance of the CombatController. However, I'm not sure if this doesn't have possible side effects.
So, lots of text for a simple question, is that safe to do?
I use inheritance in Unity all the time. The trick, like you have in the question, is to allow your base class to inherit from monobehavior. For Example:
public class Base Item : Monobehavior
{
public string ItemName;
public int Price;
public virtual void PickUp(){//pickup logic}
//Additional functions. Update etc. Make them virtual.
}
This class sets up what an item should do. Then in a derived class you can change and extend this behavior.
public class Coin : BaseItem
{
//properties set in the inspector
public override void PickUp(){//override pickup logic}
}
I have used this design pattern a lot over the past year, and am currently using it in a retail product. I would say go for it! Unity seems to favor components over inheritance, but you could easily use them in conjunction with each other.
Hope this helps!
As far as I can see this should be safe. If you look into Unity intern or even Microsoft scripts they all extend/inhert (from) each other.
Another thing you could try would be the use of interfaces, here is the Unity Documentation to them: https://unity3d.com/learn/tutorials/topics/scripting/interfaces if you want to check it out.
You are right that GameObject.Find is pure code smell.
You can do it via the inheritance tree (as discussed earlier) or even better via interfaces (as mentioned by Assasin Bot), or (I am surprised no one mentioned it earlier) via static fields (aka the Singleton pattern).
One thing to add from experience - having to have Inits() called in a specific order is a yellow flag for your design - I've been there myself and found myself drowned by init order management.
As a general advice: Unity gives you two usefull callbacks - Awake() and Start(). If you find yourself needing Init() you are probably not using those two as they were designed.
All the Awakes() are guaranteed (for acvie objects) to run before first Start(), so do all the internal object initialisation in Awake(), and binding to external objects on Start(). If you find yourself needing finer control - you should probably simplify the design a bit.
As a rule of thumb: all objects should have their internal state (getcomponents<>, list inits etc) in order by the end of Awake(), but they shold not make any calls depending on other objects being ready before Start(). Splitting it this way usually helps a lot

Duplicating Unity's mystic Interface power

Unity3D has an interface like this, for any Component on a MonoBehavior you just do this:
public class LaraCroft:MonoBehaviour,IPointerDownHandler
{
public void OnPointerDown(PointerEventData data)
{
Debug.Log("With no other effort, this function is called
for you, by the Unity engine, every time someone touches
the glass of your iPhone or Android.");
}
You do not have to register, set a delegate or anything else. OnPointerDown (the only item in IPointerDownHandler) gets called for you every single time someone touches the screen.
Amazing!
Here's a similar interface I wrote ...
public interface ISingleFingerDownHandler
{
void OnSingleFingerDown();
}
Now, I want consumers to be able to do this...
public class LaraCroft:MonoBehaviour,ISingleFingerDownHandler
{
public void OnSingleFingerDown(PointerEventData data)
{
Debug.Log("this will get called every time
the screen is touched...");
}
Just to recap, using Unity's interface, the function gets called automatically with no further effort - the consumer does not have to register or anything else.
Sadly, I can achieve that only like this:
I write a "daemon" ..
public class ISingleFingerDaemon:MonoBehaviour
{
private ISingleFingerDownHandler needsUs = null;
// of course that would be a List,
// just one shown for simplicity in this example code
void Awake()
{
needsUs = GetComponent(typeof(ISingleFingerDownHandler))
as ISingleFingerDownHandler;
// of course, this could search the whole scene,
// just the local gameobject shown here for simplicity
}
... when something happens ...
if (needsUs != null) needsUs.OnSingleFingerDown(data);
}
And I get that daemon running somewhere.
If you're not a Unity user - what it does is looks around for and finds any of the ISingleFingerDownHandler consumers, keeps a list of them, and then appropriately calls OnPointerDown as needed. This works fine BUT
the consumer-programmer has to remember to "put the daemon somewhere" and get it running etc.
there are obvious anti-elegancies whenever you do something like this (in Unity or elsewhere), re efficiency, placement, etc etc
• this approach fails of course if a consumer comes in to existence at a time when the daemon is not searching for them (Unity's magic interfaces don't suffer this problem - they have more magic to deal with that)
(PS, I know how to write an automatic helper that places the daemon and so on: please do not reply in that vein, thanks!)
Indeed, obviously the developers at Unity have some system going on behind the scenes, which does all that beautifully because "their" interfaces are perfectly able to call all the needed calls, regardless of even items being created on the fly etc.
What's the best solution? Am I stuck with needing a daemon? And perhaps having to register?
(It would surely suck - indeed generally not be usable in typical Unity projects - to just make it a class to inherit from; that type of facility is naturally an interface.)
So to recap, Unity has this:
public class LaraCroft:MonoBehaviour,IPointerDownHandler
Surely there's a way for me to make a replacement, extension, for that...
public class LaraCroft:MonoBehaviour,ISuperiorPointerDownHandler
which can then be used the same way / which shares the magic qualities of that interface? I can do it fine, but only my making a daemon.
Update
Full solution for "ISingleFingerHandler" "IPinchHandler" and similar concepts in Unity is here: https://stackoverflow.com/a/40591301/294884
You say you don't want to do a daemon but that is exactly what Unity is doing. The StandaloneInputModule class that is automatically added when you add a UI component is that daemon.
What you can do is create a new class derived from one of the classes derived from BaseInputModule (likey PointerInputModule for your case) that can handle listening to trigger and raising your extra events then add that new class to the EventSystem object.
See the Unity manual section on the Event System for notes on how to create your custom events and more details on what the input module does.
I hate to answer my own questions, but the answer here is really:
You cannot. You do have to add a daemon.
But then, it's very much worth noting that
Indeed, Unity add a daemon - they just hide it a little.
The final absolutely critical point to understand is that:
Unity screwed-up: you cannot in fact inherit from their lovely StandAloneInputModule. This is a big mistake.
Unity's StandAloneInputModule and IPointerDownHandler family - are brilliant. But you can't inherit from them properly.
The fact is, you just have to inherit sideways from IPointerDownHandler. That's all there is to it.
The fact is you have to make your own daemon ("as if" it inherits from StandAloneInputModule) which actually just goes sideways from IPointerDownHandler family.
So the actual answer is (A) you have this
public interface ISingleFingerHandler
{
void OnSingleFingerDown (Vector2 position);
void OnSingleFingerUp (Vector2 position);
void OnSingleFingerDrag (Vector2 delta);
}
public class SingleFingerInputModule:MonoBehaviour,
IPointerDownHandler,IPointerUpHandler,IDragHandler
and (B) you do have to put that on a game object (it's a daemon), and then (C) it's just stupidly easy to finally handle pinches, etc.
public class YourFingerClass:MonoBehaviour, IPinchHandler
{
public void OnPinchZoom (float delta)
{
_processPinch(delta);
}
That's it!
Full production code for PinchInputModule ...
https://stackoverflow.com/a/40591301/294884
...which indeed inherits sideways from ("uses") IPointerDownHandler family.
My assumption is that MonoBehaviour runs a type check in ctor. Which is why you cannot use the ctor on those to avoid overriding that process. The common solution is that your interface would also require to implement a registering method (Vuforia does that for instance) so any new instance registers itself.
You could also extend MB class with your own MB system:
public class JoeMonoBehaviour : MonoBehaviour
{
protected virtual void Awake(){
Init();
}
private void Init(){
if(this is ISuperiorPointerDownHandler)
{
if(ISuperiorHandler.Instance != null){
ISuperiorHandlerInstance.RegisterPointerDownHandler(this as ISuperiorPointerDownHandler);
}
}
}
}
It does not have the magic of Unity but you cannot achieve the magic of Unity with MonoBehaviour. It require the sub class to make sure it calls the base.Awake() if overriding it.
You'd have to come up with your own side engine system to run your own engine logic. Not sure that'd be worth it.
Another solution is to create your own Instantiate:
namespace JoeBlowEngine{
public static GameObject Instantiate(GameObject prefab, Vector3 position, Quaternion rotation){
GameObject obj = (GameObject)Instantiate(prefab, position, rotation);
MonoBehaviour [] mbs = obj.GetComponentsInChildren<MonoBehaviour>(true); // I think it should also get all components on the parent object
foreach(MonoBehaviour mb in mbs){
CheckForSuperior(mb);
CheckForInferior(mb);
// so on...
}
return obj;
}
internal static CheckForSuperior(MonoBehaviour mb)
{
if(mb is SomeType) { SomeTypeHandler.Instance.Register(mb as SomeType); }
}
}
Now it look like you are doing some magic only with :
JoeBlowEngine.Instantiate(prefab, Vector3.zero, Quaternion.identity);