Unity3D calling my own classes - unity3d

So I have a file with all my classes in it:
using UnityEngine;
using System.Collections;
public class Touch {
public int DoSomthing(int _test) {
int bla = _test + 1;
return bla;
}
}
public class Swipe {
}
public class Zoom {
}
How can I make it so that I can acces them in all my other scripts just like the transform class?
So I would like to acces touch like this in any other script:
int blabla = Toch.DoSomthing(5);
Without constructing the class.

Whenever you want to access class (if it's not static) you need to specify what instance of that class you want to access, if you attach your script to the main camera you can access it like this:
Toch someNameOfVar = Camera.main.gameObject.GetComponent<Toch>();
int blabla = someNameOfVar.DoSomething(5);
You create a new variable that has the type of the class you are accessing and then get the reference to specific instance of that class by specifying on what gameObject it is.
But, there is something called static class and static methods. You can change your script to this:
public class Touch : MonoBehaviour {
public static int DoSomthing(int _test){
int bla = _test + 1;
return bla;
}
}
This way you can access it without specifying which instance of it you want.
You can learn more about statics here : https://unity3d.com/learn/tutorials/modules/intermediate/scripting/statics

You make those methods static, and just call them.
public static int DoSomthing(int _test)
{
int bla = _test + 1;
return bla;
}
And then call them Touch.DoSomthing(1). It may require using on top, if you have them in another namespace.

First make DoSomthing static like this because you want to access DoSomthing by class not by instance.
public static int DoSomthing(int _test)
{
int bla = _test + 1;
return bla;
}
and if you want to apply any class on gameobject as a component make it derive from MonoBehaviour. Like if you want to attach Touch script to a game object then do this
public class Touch : MonoBehaviour {
}

Related

How can I add support for a type that references itself for a custom Reader/Writer?

I am creating a pathfinding system that I want to work with my Multiplayer game. I am using Mirror to handle networking. I created a custom Reader/Writer class so that I can send my custom type (OverlayTile) to my server.. If I don't create that custom Reader/Writer class, I get: Use a supported type or use a custom reader (At OverlayTile). .. I did create a custom Reader and Writer (I'll share below), but my question is: My OverlayTile class has a field OverlayTile previous .. I am not sure how to go about adding support for this field that references itself. The other properties have something like reader.readInt() but how could I do something similar like this for my OverlayTile type?
I have a class called OverlayTile which looks like this:
public class OverlayTile : MonoBehaviour
{
public int G;
public int H;
public int F { get { return G + H; } }
public bool isBlocked;
public OverlayTile previous;
public Vector3Int gridLocation;
}
My Reader/Writer class looks like this:
public static class OverlayTileReaderWriter
{
public static void writeOverlayTile(this NetworkWriter writer, OverlayTile overlayTile)
{
writer.WriteInt(overlayTile.F);
writer.WriteInt(overlayTile.G);
writer.WriteInt(overlayTile.H);
writer.WriteBool(overlayTile.isBlocked);
writer.WriteVector3Int(overlayTile.gridLocation);
}
public static OverlayTile readOverlayTile(this NetworkReader reader)
{
return new OverlayTile
{
G = reader.ReadInt(),
H = reader.ReadInt(),
isBlocked = reader.ReadBool(),
gridLocation = reader.ReadVector3Int(),
// previous = overlayTile.GetComponent<OverlayTile>() ??
};
}
}

Calling protected variable from another class

I need to call a protected variable from a public class into an if statement in a private method of another public class
I am programing a video game in unity and I need to use a bool variable (that shows if the character is out of stamina) in an if statement to determine whether or not the character can run
This is what my code looks like excluding everything unrelated to the problem
Public class CharacterStats : MonoBehaviour
{
[SerialzeField] protected bool Tired;
}
Public class PlayerMovement : MonoBehaviour
{
Private void HandleRunning()
{
If (Input.GetKeyDown(KeyCode.LeftShift) && X != True)
{
Speed = RunSpeed;
}
}
}
X is where I want the Tired variable to be.
Use a public readonly property like e.g.
public class CharacterStats : MonoBehaviour
{
// Keep you serialized field protected
[SerialzeField] protected bool tired;
// Have a public read-only accessor property
public bool Tired => tired;
}
and then e.g.
public class PlayerMovement : MonoBehaviour
{
// Somehow you will need to get a reference to the CharacterStats instance
// e.g. via the Inspector
[SerializeField] private CharacterStats stats;
[SerializeField] private float RunSpeed;
private float Speed;
private void HandleRunning()
{
if (Input.GetKeyDown(KeyCode.LeftShift) && !stats.IsTired)
{
Speed = RunSpeed;
}
}
}
Alternatively (and my apologies to #aybe who had answered this) you can actually directly serialize a property using explicitely
[field: SerializeField] public bool Tired { get; protected set; }
this is a property which can be accessed by everyone but only this and inherited classes (and due to the serialization now the Inspector) have the permission to set the value.
In general: Fix your casing! In c# all keywords are lower key!

Custom onClick list

Can i create custom region with grouped methods for list onClick like dynamic and statics?
like this
Yes and no! ^^
Yes, you can create your own event type taking a parameter and assign dynamic callbacks to it. What you are looking for is UnityEvent.
For the dynamic parameterized ones see UnityEvent<T0> to UnityEvent<T0, T1, T2, T3> depending on how many parameters you need.
For the example with a single int it would be (exactly as in the API example)
// Since Unity doesn't support direct serialization of generics you have to implement this [Serializable] wrapper
[Serializable]
public class MyIntEvent : UnityEvent<int>
{
}
public class ExampleClass : MonoBehaviour
{
public MyIntEvent m_MyEvent;
}
No, you can not simply change the existing implementation of UI.Button.onClick which is parameterless.
What you could do, however, is build a new component and attach it on a button like
[RequireComponent(typeof(Button))]
public class ExampleClass : MonoBehaviour
{
[SerializeField] private Button _button;
public MyIntEvent onClickWithIntParameter;
private void Awake()
{
if(!_button) _button = GetComponent<Button>();
_button.onClick.AddListener(HandleOnClick);
}
private void HandleOnClick()
{
// Wherever you get your int from
var value = 123;
onClickWithIntParameter.Invoke(value);
}
}
In the case that [Serializable] isn't working for you try [System.Serializable] or using System; at the top.
For Those who want to create a custom event Script:
I made a collision detection script. The events set in the inspector are called when a collision is detected. Just like a button.
https://i.stack.imgur.com/r4epP.png
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngine.Events;
public class CollisionCallFunc : MonoBehaviour {
[System.Serializable]
public class CollisionEvent : UnityEvent<object> {
public object value;
}
[SerializeField]
private CollisionEvent collisionEvents = new();
private void OnCollisionEnter(Collision collision) {
try {
collisionEvents.Invoke(collisionEvents.value);
} catch(System.Exception exception) {
Debug.LogWarning("Couldn't invoke action. Error:");
Debug.LogWarning(exception.Message);
}
}
private void OnCollisionEnter2D(Collision2D collision) {
try {
collisionEvents.Invoke(collisionEvents.value);
} catch(System.Exception exception) {
Debug.LogWarning("Couldn't invoke action. Error:");
Debug.LogWarning(exception.Message);
}
}
}

Global Scriptable Object

Suppose I have this ScriptableObject to represent a list of cards:
using UnityEngine;
using System.Collections;
[CreateAssetMenu(fileName = "CardList", menuName = "Inventory/List", order = 1)]
public class CardList : ScriptableObject {
public string[] cardName;
public Sprite[] cardSprite;
}
Then I create the ScriptableObject and fill it with all my cards information.
Is there a way to modify this code so that any script have access to it statically? For example, is it possible to give CardList a singleton behaviour?
I don't want to create another class, it would be easy to create a ScriptableObjectManager that could reference CardList. I'd rather call something like CardList.instance.cardName[i] directly.
Definitely, you can create it as singleton so for this.
Suppose that we have Unity Project that has file hierarchy like
UnityProject
- Assets (directory)
Scripts
SampleScriptableObject.cs
- Resources (directory)
SampleScriptableObject.asset
- Project
- ..etc
in "SampleScriptableObject" class will be like
public class SampleScriptableObject<T> : ScriptableObject where T : ScriptableObject
{
private static T _instance;
public T GetInstance()
{
if (_instance == null)
{
_instance = Resources.Load(typeof(T).Name) as T;
}
return _instance;
}
}
you can use scriptable object as singleton as you want.

Unity: GetComponent<BaseClass<T>> - are there any workarounds for this?

If an object has a component with a baseclass BaseClass<T>, calling GetComponent<BaseClass<T>>() will not return that component. The generic argument seems to throw it off, as a BaseClass without using generics will correctly return the derived class as a component when GetComponent<BaseClass>() is called.
Does anyone know a solid workaround for this? The use of a generic arg in this class is somewhat important, so I'd obviously rather not re-write the program's class structure just to accommodate this.
Here's a rough sketch of the classes in question
//the base class that I'd like to be able to fetch the subclasses of using GetComponent
public abstract class BaseUIClass<T> : MonoBehaviour where T :BaseEntity {}
//EntityType1&2 are derived from BaseEntity
public class DerivedUIClass1 : BaseUIClass<EntityType1> {}
public class DerivedUIClass2 : BaseUIClass<EntityType2> {}
BaseUIClass has this method:
public virtual void Setup(T entity) {}
Which needs to be called shortly after the component is added to a GO.
EDIT:
Effectively what I'm looking to do is the following, without having to hard-code in (I want to actually make use of the generic args I've defined)
if(uiClassObj is typeof(DerivedUIClass1) go.GetComponent<BaseUIClass<EntityType1>>();
else if(uiClassObj is typeof(DerivedUIClass2) go.GetComponent<BaseUIClass<EntityType2>>();
//etc
But considering that there is a component of type BaseUIClass<BaseEntity> on the go, and the two+ derived classes I'm interested in are defined by DerivedUIClass1<EntityType1> and DerivedUIClass2<EntityType2>, the conversion should surely just be implicit?
You can't do what you want the way you want, because Unity doesn't accept components which are generic classes.
I.E., if you have:
public class MyGenericClass<T> : MonoBehaviour {}
you will not be able to add it as a component unless you specify T via a subclass inheriting from it:
public class MySpecifiedClass : MyGenericClass<[specificType]> {}
So, to solve your problem, you should simply implement a specific interface for everything that should be done when the base class is added as a component. I'll show you an example with float and int derived types, you can extend easily to any type you need.
BaseClass
using UnityEngine;
public interface ISetup {
void CallSetup();
}
public class BaseClass<T> : MonoBehaviour, ISetup {
public T myEntity;
public void CallSetup() {
Setup(myEntity);
}
private void Setup(T entity) {
Debug.Log(entity);
//Your setup code
}
}
Your components classes
public class BaseClassInt : BaseClass<int> {
private void Awake() {
myEntity = 25;
}
}
public class BaseClassFloat : BaseClass<float> {
private void Awake() {
myEntity = 10.6f;
}
}
Code that gets the interface and calls Setup()
var componentsWithSetup = GetComponents<ISetup>();
foreach (var component in componentsWithSetup) {
component.CallSetup();
}
One workaround would be to use a specific type instead of a generic type at the top level for each type that you need the base class for.
For example:
public class SpecificToFirstTypeClass : BaseClass<FirstType>
{
}
and then use GetComponent<SpecificToFirstTypeClass>
Based on a suggestion from this answers.unity.com question
I couldn't believe this didn't work so I hacked it using tags, where UI is a base, abstract class:
public UI currentUI;
public void GetUI()
{
foreach (Transform child in transform)
{
if (child.tag == "UI Canvas")
{
currentUI = child.GetComponent<UI>();
}
}
}
Where I may have a different active "UI" depending on the scene. It might be the main game scene, or the menu scene. Now, I can just interact with the UI manager via generic/abstract methods like LoadUI() or HideUI().
Tbf, this really should be handled by events but it's overkill for my current project.