I have a field of type Color, let's call it objectColor. I want objectColor "point" to a gameobject that has a color field. For example, the background color of the camera. Or the color of a sprite renderer. When I try "objectColor = mainCamera.backgroundColor" for example, it copies the main cameras background color at that time, and is not linked. I am used to pointers and C++. If I was in C++ I would just make a pointer of Color type, make it point to what mainCamera.backgroundColor is pointing to, and then change the color that way. Any suggestions?
No simple way to do that in C#. You could either hold reference to the class, that owns Color field, but this will prevent you from changing colors of different object types (not sure it is bad actually). Or you could make class wrappers around all objects with color changing functionality and use them through common interface.
interface IColorChange {
void SetColor(Color color);
}
class CameraWrapper : IColorChange {
public void SetColor(Color color){
m_camera.backgroundColor = color;
}
}
Actually, if you think about it, storing member pointer in c++ is also not such a great idea. Class instance could die any time and you will be left with a dangling pointer without any way to know about it.
One somewhat unusual way (but not necessarily bad if documented well) would be to use "properties". Those are variables which automatically call their custom setter and getter methods when accessed. You cannot avoid separately keeping a reference to the camera instance with them either however.
Here an unity-independent example: https://dotnetfiddle.net/oxBqXV
using System;
public class Camera
{
public int color = 20;
}
public class Foo // most likely should inherit from MonoBehavior
{
Camera _camera;
public int cam_color_ptr // property
{
get
{
return _camera.color;
} // get method
set
{
_camera.color = value;
} // set method
}
public void Start()
{
// of course you should acutally get the reference here
// or have _camera a serializable field to assign in the editor.
_camera = new Camera();
}
public void Print()
{
Console.WriteLine("The camera color is: " + cam_color_ptr);
}
}
public class Program
{
public static void Main()
{
Foo foo = new Foo();
foo.Start();
foo.Print();
}
}
Related
I have a scene that is a Paddle (like the one in PONG game). But my paddles can be either horizontal either vertical.
So I made one parent abstract class "Paddle" that contains the common logic, and two derived classes that extends Paddle "PaddleHorizontal" and "PaddleVertical" where the movements are different (one go up and down, the other go left and right).
At the beginning, I want to create my paddles and attach correct script to each of them but I got this error
" Script inherits from native type 'KinematicBody2D', so it can't be instanced in object of type: 'PackedScene' "
My Main.cs is like so :
using Godot;
public class Main : Node2D
{
private PackedScene _paddleScene;
public override void _Ready()
{
base._Ready();
_paddleScene = GD.Load<PackedScene>("res://src/scenes/entities/paddle/Paddle.tscn");
var script = GD.Load<Reference>("res://src/scenes/entities/paddle/PaddleHorizontal.cs");
_paddleScene.SetScript(script);
this.InitPaddles();
}
private void InitPaddles()
{
this.AddPaddle(new Vector2(PaddlePositions.Top.x, PaddlePositions.Top.y));
this.AddPaddle(new Vector2(PaddlePositions.Bottom.x, PaddlePositions.Bottom.y));
}
private void AddPaddle(Vector2 paddlePosition)
{
KinematicBody2D paddleInstance = (KinematicBody2D)_paddleScene.Instance();
paddleInstance.Position = paddlePosition;
AddChild(paddleInstance);
}
}
// -- Paddle.cs --
using Godot;
public abstract class Paddle : KinematicBody2D
{
// common methods & properties
// the one method that is different and should be override
public abstract Vector2 GetMovement();
}
// -- PaddleHorizontal.cs --
using Godot;
public class PaddleHorizontal : Paddle
{
public override Vector2 GetMovement()
{
// different from PaddleVertical
}
}
I guess the error come from the fact that PaddleHorizontal don't extends KinematicBody2D directly but there is a lot of logic that will be in common between the 2 types of Paddle... .. If you guys have a solution or a workaround...
EDIT: A workaround has beed found by mxmissile in comments. Instead of setting the script of PackedScene, he proposed to set it on the Instance. And it works. Check https://github.com/godotengine/godot/issues/31994 for more details and DO READ the first comment in order to avoid another issue.
The solution suggested by #mxmissile looks like:
private void AddPaddle(Vector2 paddlePosition)
{
KinematicBody2D paddleInstance = (KinematicBody2D)_paddleScene.Instance();
ulong paddleInstanceId = paddleInstance.GetInstanceId();
Resource script = GD.Load("res://src/scenes/entities/paddle/PaddleHorizontal.cs");
paddleInstance.SetScript(script);
paddleInstance = (KinematicBody2D)GD.InstanceFromId(paddleInstanceId);
paddleInstance.Position = paddlePosition;
AddChild(paddleInstance);
}
The Error
Script inherits from native type 'KinematicBody2D', so it can't be instanced
in object of type: 'PackedScene'
This error is caused by setting the script of an Object to a script of a
different object hierarchy.
The same error will occur if you, for example, set the script of a Control node
to a script that inherits from Node2D.
The Solution
Instead of set_script() of the _paddleScene you should set_script() of the
paddleInstance which is the instance of KinematicBody2D.
KinematicBody2D paddleInstance = (KinematicBody2D)_paddleScene.Instance();
paddleInstance.SetScript(thePaddleScript);
I am a novice programmer, so sorry if this is a really stupid question. I need to pass a value from one class to another. If I am not mistaken, this would be done through inheritance, but there seems to be something I am missing. Any help would be welcome. I am writing in C# within Unity.
public class baseStats{
private int STAMINA;
public static int Stamina{
get{return STAMINA;}
set{STAMINA = value;}
}
}
The above is a sample of my parent class. Here is my child class:
public class Profile : baseStats {
private static int PROFILE_STAMINA;
private void Stats ()
{
PROFILE_STAMINA = Stamina;
}
public static int profileStamina
{
get{return PROFILE_STAMINA;}
}
}
In a third script I created for the purposes of debugging, I wrote:
public class debug:MonoBehaviour{
void Start(){
Debug.Log(Profile.profileStamina.ToString());
}
}
It says I need an object reference for the non-static field, method, or property
'Profile.Profile.Stamina'. Easy fix: make everything static (I believe I need to make constructors or something like that to avoid having to use static all the time. A little help with that would be great!). Once error-free, I ran the program and the console outputs 0 for my profile stamina. I am really confused as to what is going on. Sorry this is such a long post, and thanks for any help I get.
I need to pass a value from one class to another. If I am not
mistaken, this would be done through inheritance.
No, you don't need inheritance to pass values from one class to another. If you don't know what inheritance is, you shouldn't be using it. It's very likely you don't need it. The-same thing applies to the static keyword. New programmers tend to make everything static when they don't know what the new keyword is used for.
Simply create a new instance of the Stats script inside the Profile constructor script. To use the Profile script, create a new instance of it which will automatically call the constructor that will create a new instance of the Stats script. You shouldn't be doing this with static variables and functions. Totally unnecessary. Values can be passed to another script with auto property or function but my solution used auto property to make it simple.
public class Stats
{
private int STAMINA;
public int Stamina
{
get { return STAMINA; }
set { STAMINA = value; }
}
}
public class Profile
{
private Stats stats;
private int PROFILE_STAMINA;
//Init only
public Profile()
{
stats = new Stats();
}
//Init with Stats stamina and profileStamina stamina values
public Profile(int stamina, int profileStamina)
{
stats = new Stats();
stats.Stamina = stamina;
PROFILE_STAMINA = profileStamina;
}
//Stamina From Profile
public int profileStamina
{
get { return PROFILE_STAMINA; }
set { PROFILE_STAMINA = value; }
}
//Stamina From Stats
public int Stamina
{
get { return stats.Stamina; }
set { stats.Stamina = value; }
}
}
Usage:
public class debug:MonoBehaviour{
Profile profile = null;
void Start()
{
//Creata new profile and set Stats stamina and ProfileStamina stamina values
profile = new Profile(10, 5);
profile.Stamina = 60;
profile.profileStamina = 60;
Debug.Log(profile.profileStamina.ToString());
}
Also take time and learn about Classes,Properties.
You're trying to access a non-static from a static property.
This code is the main problem:
public static int Stamina{
get{return STAMINA;}
set{STAMINA = value;}
}
STAMINA is defined as private int STAMINA. It isn't static. Quite simply, this means that inside every object of the type baseStats you have an int called STAMINA you can fill in. However, you're not working on an object there; you're in a static function, which is something that can be executed without an object. Since there is no object, there is no STAMINA int either; there's no object to get or fill in that property on.
On that note, your function profileStats() has the same issue; it tries to access the non-static STAMINA as well, again without having any kind of object. Any reference to just plain STAMINA is actually to this.STAMINA, and inside a static, there's no this.
I'm not sure what the purpose of this whole setup is; personally I'd avoid using statics containing global data like that. Instead I'd just keep an object around containing the necessary properties which is simply passed on to any functions that need to access the data in it. But anyway, from what I can see, you simply forgot to put static on that private int STAMINA.
Side note: this is completely unrelated to inheritance. Since Stamina is a public static property, and statics can't be inherited (except in some peculiar advanced cases with inherited generics), your "child class" never even needs the parent class as parent, as long as it references baseStats.Stamina instead of STAMINA. This can easily be shown by making both classes static.
I am trying to write some code in C# with unity where i have an object who's position I need to know for my script to work. I was trying to use a pointer as that's what I thought was used. It said i had to use an unsafe tag which made me think i was doing something wrong. I am a little new to this and so far i have most of my knowledge with C++ as that's what i have learned in class. I tried looking it up but i could not find it. this is basically what i have right now.
using UnityEngine;
using System.Collections;
public class SGravSim : MonoBehaviour {
public GameObject moon;
public GameObject earth;
private struct Cords
{
public float* x
{
get
{
return x;
}
set
{
if (value != 0) <== this thing is realy just a placeholder
x = value;
}
}
public float* y
{
get
{
return y;
}
set
{
if (value != 0) <== this this is only in here for now
y = value;
}
}
public void DisplayX()
{
}
}
private Cords moonLocation;
private Cords earthLocation;
private Cords SataliteLocation;
// Use this for initialization
void Start () {
moonLocation.x = moon.transform.position.x;
moonLocation.y = moon.transform.position.y;
earthLocation.x = earth.transform.position.x;
earthLocation.y = earth.transform.position.y;
SataliteLocation.x = this.transform.position.x;
SataliteLocation.y = this.transform.position.y;
}
// Update is called once per frame
void Update () {
Debug.Log(moon.transform.position.x);
//
// Summary:
// The position of the transform in world space.
float yMoon = moon.transform.position.x
print(moonLocation.y);
}
}
I was planing on making the set so that you could not add anything to it.
I guess I could write out the whole earth.position.x thing every time I need to use it I was just trying to see if there was a better way to do it and also a way where I cant mess with the variable as all I want to do is read it.
You can use private set in the automatic properties :
public float X {get; private set;}
This way only your class will be able to set the variable but any other class wouldn't.
You shouldn't use pointers in c# except for really specific cases.
The solution several people gave you here is good:
public float X {get; private set;}
It is called a property and is one of the nice possibilities in c# to avoid creating getters and setters.
You say you have some knowledge in c++, but c# is actually closer to higher languages such as java. You should focus on the Object Oriented way to code and forget about low level pointers, especially using Unity.
You can use:
private float x;
public float X
{
get
{
return x;
}
}
Now you only set x from within your class.
You get the unsafe tag warning, because you try to use pointers, which are actually unsafe. There might be use-cases for that, but in C# you generally use reference types and value types. In C# a struct is a value type, so it will behave differently compared to a reference type, as you can read here, which is also why Gubr has suggested to use a class instead of a struct. Last but not least, there is a difference in how they are stored, just google C# heap and stack.
I haven't used structs that much in C# yet, so I just created a new project and played a bit around.
So I used your code, which also could just look like this:
private struct Cords
{
public float x, y;
public void DisplayX(){}
}
As the others have mentioned, you could leave out the set or make it private and add a constructor. Mind you, a private set doesn't equal to not defining it in auto-properties. Instead, it will create a readonly field. However, you have to call the new operator in both cases to set the value:
private struct Cords
{
public float X { get; }
public float Y { get; }
public void DisplayX(){}
public Cords(float x, float y)
{
X = x;
Y = y;
}
}
And here we create a new Cords:
Cords earth = new Cords(10.005f, 12.689f);
I have my main program which contains an array called setOfBalls[i] which stores ellipses. The ellipses have three properties:
setOfBalls[i].velocity;
setOfBalls[i].direction;
setOfBalls[i].mass;
Then I have a collision class and need to be able to access the arrays with direction, velocity and mass in the collision class called Collisions.cs.
I need to be able to detect a two body collision out of my three balls but I do not know how to get the array from main program to my collision class?
public Boolean twoBodyCollision()
{
}
Consider adding parameters to your method and send the array as an argument; e.g.
public boolean HasCollidingObjects(Ball[] listOfBalls) { // ... }
Here I assume you're using a Ball class, but it's only an example. Use your class instead.
Also, you should use C# naming conventions instead of Java's. You can check the MSDN pages for information on what these are.
To pass an object into a class, you can use a constructor:
private string[] setofBalls;
public ClassName(string[] setBalls)
{
setofBalls = setBalls;
}
public void DoSomething()
{
foreach (string ball in setofBalls) { ...... }
}
More on Object Oriented Programming with C#: https://msdn.microsoft.com/en-us/library/dd460654.aspx
You can create an instance of the class you have your method in then call if from your "main program"
public void MethodInMainProgram()
{
Collision collision = new Collision();
collision.TwoBodyCollision(setOfBalls);
}
public class Collision
{
public void TwoBodyCollision(Ellipse[] ellipses)
{
//logic that detects collisions
}
}
more info on creating instances here
For example
Public int Width
{
get { return Something.Width; }
}
instead of
Public int Width;
//later in the code
Width = Something.Width;
or
Public int Width = Something.Width;
Accessors are a very powerful feature, that allows you to attach methods and advanced visibility modifiers to your properties.
Fake Read-Only Example
public class Entity
{
// This Health variable looks like a read-only variable from the outside, but is still settable outside the constructor.
public Single Health { get; private set; }
// This Resistance variable looks like a read-only variable from the outside, but is still settable outside the constructor.
public Single Resistance { get; private set; }
public void Damage(Single amount)
{
this.Health -= Math.Max(amount - this.Resistance, 0.00f);
}
}
Method Example
public class Entity
{
private World world;
public World World
{
get { return this.world; }
set
{
// This will ensure the entity is always added and removed correctly from the world it is set to belong to.
if(this.world != null)
this.world.RemoveEntity(this);
this.world = value;
if(this.world != null)
this.world.AddEntity(this);
}
}
}
Advanced Visibility Example
public class Entity
{
// This gives you a read-only style property, which can still be set by other classes inheriting this class, as the setter is protected.
public Vector2 Position { get; protected set; }
}
I'm sure there are plenty of other examples, but this is some of the reasons accessors are a wonderful tool.
Note that an accessor always gets the default value, and you can only change this in the constructor.
Default values
byte, short, int, long, float, double: Zero
string: An empty string.
classes: null
structs: The default value for their members types.
1) Width is just a question you can ask about an object, how wide are you? Outside you don't really care how width is dealt with inside, you just care about what is the answer.
2) Width may change, right now it's just a width member variable but later maybe it's a calculation or maybe the object is really a list of other objects. The object itself should be responsible for all that and not someone outside who is not-the-object.
3) The less outside objects know about how and the more they only care about what the easier it is to understand code you or someone else wrote a year ago.
4) It centralizes control over the width property of that class which means that code is all in one place and easy to maintain. Any other way if something changed then code all over your program has to change, too, and that's just a big mess ;-)
5) The same goes with using setters instead of just shoving a number into Something.Width directly.
So basically it's a way of keeping the inside world of an object safe from the outside and making it really easy to change how an object works without disturbing the rest of your program.