I want to overwrite a read-only variable to simulate fingertouch with mouse in my code:
Touch fakeTouch = new Touch();
fakeTouch.position = Input.mousePosition;
The error I am getting is:
UnityEngine.Touch.position cannot be assigned to (it is read only).
How can I change it to public or so to overwrite it?
Here is what I want to do in the reply: Convert UnityEngine.Vector3 to UnityEngine.Touch or mouse input
In Unity 5.6, you cannot overwrite the position field in the Touch class, since it is used as a C++-compatible container structure and not intended to be created directly in the runtime.
Define a public sealed class TouchEx that contains the fields you need, and bypass the Touch object in your own code.
Related
Preamble
I am currently making a game where a player can go from third person view, walking around to transition into a vehicle.
I have thought about using a transmitter/receiver type set up, but I think my way of simplifying it isn't correct.
I am using assets from third parties for controllers that use inputs. My plan was to enable/disable the appropriate script and camera from the object I want to control. I've gotten as far as being able to disable the previous controller and enable the next, though I can't go back to enabling since the script obviously doesn't run anymore.
Question/Request
I'd like to be able to reference the pawn's input component script in a different component script on the same gameobject to then be able to enable/disable the aformentioned component, though the issue is that the input controllers have variable names (Different names depending on the third party on each pawn).
Here's how I have it set up:
I have a PlayerTransmitter that handles the basics of turning things on and off. I tried making this where all of the inputs are being handled, but I don't want to have to change the original controller scripts to look at this script. This is on an empty game object and handles the 'state' of the player, (walking or in which vehicle).
on each pawn gameobject (The walking pawn CleanerPawn and the vehicle TractorPawn), I've added a script called InputReceiver. This was originally intended to pass the inputs from the PlayerTransmitter to the actual controller on the object itself.
Right now, the walking pawn has a component called AdvancedWalkerController (You may know the one I'm talking about) that controls the player walking movement and the vehicle has a component called VehicleController which controls how the vehicle moves and handles.
CleanerPawn
TractorPawn
The two images above show that I am using the same InputReceiver component on both pawns. My plan was to pass in each pawn's input controller (temporarily named CleanerController) and then enable/disable that input controller depending on the PlayerTransmitter 'state'.
The InputReceiver currently looks like this:
public bool isEnabled;
public Component CleanerController;
public void TurnOffControls()
{
isEnabled = false;
}
public void TurnOnControls()
{
isEnabled = true;
}
In each pawn's input controller, I added a line to the Update() function:
enabled = gameObject.GetComponent<InputReceiver>().isEnabled;. Two problems with this; 1. I don't want to change any code in the input scripts (I hope this is possible) and 2. Once it's disabled, it won't read an update to enable itself again.
I was hoping I could just use the reference to the component CleanerController to say CleanerController.enabled = true; or false with that reference being just that one component, though I'm missing something here.
My final thought which I am going to try is to allow/disallow the input controls within each input script depending on my isEnabled boolean. Though again, I would have to change the original scripts to accommodate this.
What speaks against
public Behaviour CleanerController;
and then
CleanerController.enabled = false; // or true accordingly
See
Behaviour
Behaviours are Components that can be enabled or disabled.
Behaviour.enabled
Enabled Behaviours are Updated, disabled Behaviours are not.
or in other words: If a Behaviour is set to enabled = false then it's Update (and similar event methods) is not called anymore.
I would recommend you to have a Controller Script. This named "CameraController" for example and has a Method to switch between the Modes. This would also make it possible to have even more Options. For Example you could use an Enum to define which modes exist:
enum CameraMode {
Player,
Car
}
public SwitchMode(CameraMode mode) {
switch(mode) {
case CameraMode.Player:
TurnOnControls();
break;
case CameraMode.Car:
TurnOffControls();
break;
default:
throw new NotSupportedException();
}
}
You could even go further and create an Interface/Abstract which allows all of this and just has an execute method doing different stuff. In the end you just need that controller which allowes to swtich between the modes and handles the key input.
I hear people talking about serializing variables among things in their unity projects and quite don't understand it. I see them using
[SerializeField]
and don't know why or what it does.
I looked up the definition of data serialization: Serialization is the process of converting the state information of an object into a form that can be stored or transmitted.
During serialization, objects write their current state to temporary or persistent storage. Later, the object can be recreated by reading or deserializing the state of the object from the store.
Objects are created as the program runs, and then reclaimed when unreachable, with a short lifespan. But what if we want to store the contents of the object permanently?
Convert it into a sequence of bytes and save it on a storage medium. Then serialization is required. [SerializeField] is to force Unity to serialize a private field. This is an internal Unity serialization function. Sometimes we need to Serialize a private or protected attribute. In this case, the [SerializeField] attribute can be used.
The above is some information I found, I hope it is correct and can bring you some help
Say, you have a field _speed and you want to set it using inspector. It means we want it to be serialized - stored somewhere in a human-readable and flexible format(e.g. xml), not directly in code. So when you edit fields in inspector, you edit the serialized data. During compilation, it's being deserialized and assigned to a field. This is how serialization/desearialization works. It is used to store non-static or just big amounts of data. In case of Unity it is used to show you everything in inspector. Transform has position and scale variables serialized and you can edit them.
In Unity there are two common ways to make fields assignable in inspector: using public fields or using [SerializedField] attribute for private ones.
Making fields public just to edit them with inspector is bad practice. If you can edit field in inspector, it means every other component can too, which is insecure. There is no good architecture that allows such things. If you want other components to edit the field, make it a property or make a set method. If you just need to assign fields by hand, don't use public fields. Avoid them.
When you use the [SerializeField] attribute, you create a private field that is accessible to this component only and you can assign it in inspector at the same time. If you need other components to read it, you can make a public property without set (public float Speed => _speed;).
This all is not an obligatory usage. Just good practice.
Any values set in the Unity inspector for any public fields or private/protected fields that use the attribute [SerializeField] are saved with the current scene file.
If you open up a Unity.scene file you will find a hierarchy of data that matches the scene hierarchy along with lists of what script or component classes are attached to that game object and what the field values of those classes/components should be.
When loading a level in Unity, the scene file is deserialized meaning that a program walks the data structure creating game objects. It then creates component and script class instances attached to those components and initializes them with the serialized data in the scene file. After that you end up with a level more or less the same as it was when saved in the unity editor.
In addition to your own Monobehaviour scripts having this ability, all the default unity components work this way. Transform uses serialized Vector3s for position, rotation and scale. MeshFilter components serialize a reference to a mesh asset and the MeshRenderer component references Materials that are used by the GPU to draw the mesh etc etc.
In short, serialisation is a process by which computers transform data so that it can be written to a file (or sent across a network via a protocol stream) and then later transformed back into the original set of objects it was to begin with (or as close as matters).
I'm working a game in Unity and I've got a Script where I save a lot of values in multiple variables, which I then use in other scripts. You could say its my GameState. The Script itself is not a GameObject, it purely exists to save values. When I start my game the "GameState" has some basic values like Name, TeamName, Money and tons of more variables which are static and filled with pre-set values.
Now comes my problem. If the player plays through the game and picks some options, functions get triggered which change the values in the GameState, like for example he'll receive more money, so the value for money in the GameState changes. But the player also has the option to completely "restart" the game by going back to the main menu (where I use a LoadScene Function). Problem is that the values in the GameState remain changed when he goes back, so when he starts a new game, he doesn't got the pre-set values, but the ones from his last game.
So my question would be, is there an easy way to reset my GameState completely to its original values? I know I could save the default values somewhere and then make a check to see if the game is reloaded to then use them, but I've already got like 60-70 variables in there and don't really want to create another 60-70 just for the default values (unless there is no other option). So does anyone have an idea how I could do that?
I don't think showing the code of the GameState does much, since its really just looking like:
public class GameState
{
//Team
public int TeamID;
public string TeamName;
public string TeamColor;
etc...
}
GameState is a class to contain data. An easy way to create default is to serialize it : add [System.Serializable] on top of the class declaration.
Now you can have say an object in your main scene called default values which has a public/serialized field of type GameState. You can set those in the editor save the scene and bam. Now to reset all the values to default you just copy the default to the current/active set of data.
If you want to expand a bit on that you can also turn the class into a scriptableObject but I don't think you need that.
I am having problems mutating referenced values through using Unity's API for modifying the Editor GUI.
When I go into the editor to change the values in the GUI, it just refreshes and retains the label text/object I provide in the arguments, why isn't it mutating the reference and displaying that instead?
1.
I am referencing a class attached to a particular Game-object ButtonManager script = target as ButtonManager;
I want to change the values of that class script.thisImageCaption = EditorGUILayout.TextArea("Content for the main image slide", script.thisImageCaption); but this does not work
odly though... bools work, when I check the box, the GUI remembers my choice and modifys the referenced value, so why don't the others?
script.hasAudioClip = EditorGUILayout.Toggle("Voice Over?", script.hasAudioClip);
2.
I am also referencing GameObjects and their Individual Components
//following code is a snippet of code, the full context isnt provided, only the context related to mutating referenced values
List<Tuple<int, Text, Image>> imageCloneHolder = new List<Tuple<int, Text, Image>>();
imageCloneHolder.Add(new Tuple<int, Text, Image>(
slide.GetInstanceID(),
slide.transform.GetChild(1).GetComponent<Text>(),//get reference to text
slide.transform.GetChild(0).GetComponent<Image>()//get reference to image
));
item.Item2.text = EditorGUILayout.TextArea("Content for the image cloneslide",
item.Item2.text);//dosen't modify the referenced text
item.Item3.sprite = EditorGUILayout.ObjectField("This second Image slides image",
item.Item3.sprite,
typeof(Sprite),
false) as Sprite;//doesn't modify the referenced image
I don't quite understand what's wrong, I thought when you grabbed references in Unity & C#(with classes,components, etc) they would be pointers to the real object not a copy, but it appears Unity's API for the GUI is having me modify copies? Is this not true for strings referenced in a class? Or for some Unity Components?
Screen Dump
Code: https://imgur.com/a/5fRR56c
Editor: https://imgur.com/a/jeXMGSN
The main issue I guess is that you don't mark stuff as dirty. This is required to save any changes.
In general you should not directly make changes to the target from within an Editor. Rather use SerializedProperty. They handle all the marking stuff dirty (thus saving changes) and Undo/Redo functionality for you.
Also I don't see why you are using a List there if anyway you are adding only one element...
I don't see your full code especially the class and full Editor would be helpful. But for what you provided it should be something like
public class YourEditor : Editor
{
private SerializedProperty thisImageCaption;
private SerializedProperty hasAudioClip;
// wherever you get this from
private XY item;
private void OnEnable()
{
// Link SerializedProperties to the real ones
thisImageCaption = serializedObject.FindProperty("thisImageCaption");
hasAudioClip = serializedObject.FindProperty("hasAudioClip");
}
public override void OnInpectorGUI()
{
// Load the current real values
// into the SerializedProperties
serializedObject.Update();
// Now only change the SerializedProperties
thisImageCaption.stringValue = EditorGUILayout.TextArea("Content for the main image slide", thisImageCaption.stringValue);
// Using PropertyField automatically
// uses the property drawer according
// to the property's type
EditorGUILayout.PropertyField(hasAudioClip);
// now to the tricky part
// for both slider sub-components you will need
// to create a serializedObject from the given components e.g.
var textSerializedObject = new SerializedObject(item.Item2);
var imageSerializedObject = new SerializedObject(item.Item3);
// do the update for both
textSerializedObject.Update();
imageSerializedObject.Update();
// now change what you want to change via serializedProperties e.g.
EditorGUILayout.PropertyField(textSerializedObject.FindProperty("m_text"), new GUIContent("Content for the image cloneslide"));
EditorGUILayout.PropertyField(imageSerializedObject.FindProperty("m_Sprite"), new GUIContent("This second Image slides image"));
// Write changes back to the real components
textSerializedObject.ApplyModifiedProperties();
imageSerializedObject.ApplyModifiedProperties();
serializedObject.ApplyModifiedProperties();
}
}
Note: Typed on smartphone so no warranty but I hope the idea gets clear.
After reading the API info here:
https://docs.unity3d.com/ScriptReference/TrailRenderer-colorGradient.html
I am wondering if I can "tune in" my trail renderer in the normal unity interface, print those complicated code parameters, then use that code in my script to change color on triggers, etc.
To clarify, how do I get the information here presented in code:
[]
I guess I am approaching this from a CSS background. Is there a Unity colorgradient version of this website:
https://www.colorzilla.com/gradient-editor/
Can I make the script print the characteristics of the trail renderer (for the purpose of replicating it elsewhere in my code)?
1
Much appreciate the help!
I'm still not 100% sure if I understood the question but I'll give it a shot.
As I understand you want to have a component on every trigger object where you can define different gradient settings for each.
And I assume by Unity interface you mean the Inspector.
So something like e.g.
public class GradientSetter : MonoBehaviour
{
public GradientColorKey[] colorKeys;
public GradientAlphaKey[] alphaKeys;
}
Put this on the trigger object(s) and adjust the settings via the Inspector. At beginning they should be empty arrays so to add elements just enter the wanted element count in the size property of both arrays.
And wherever you have the Collision implemented on your TrailRenderer object
void OnTriggerEnter(Collider other)
{
var gradientSetter = other.GetComponent<GradientSetter>();
if(!gradientSetter) return;
gradient.SetKeys(gradientSetter.colorKeys, gradientSetter.alphaKeys);
...
}
I'm assuming GradientColorKey and GradientAlphaKey are Serializable. If you implement this but they don't show up in the Inspector let me know, then you'll have to make a wrapper class for them. (I can't test it right now)
Note: Typed on smartphone so no warranty but I hope the idea gets clear