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
Related
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();
}
}
I need help to get all the traits from a list from another class then set them a specific image and show them simultaneously to the player.
To do so, I created in my UI a traitSlotContainer with a grid layout and a traitSlotTemplate GameObject with an Image. I would like this traitSlotTemplate to be used for each Trait.
I've got a class called "Npc", which represents one instance of auto generated instanciate NPCs containing their name, stats, traits, skills etc...
Class is in shorter something like that:
[Serializable]
public class Npc
{
public string NameLocalizationKey;
public int Height;
public int Weight;
public string EyeColor;
public string HairColor;
public string Haircut;
public List<Trait> Traits;
}
I would like to show the traits proper to the selected NPC.
Note that the instantiate NPC is "Selected.Npc"
I reckon that I need first to load the selected NPC trait list, get one trait, instantiate it as GameObject then change it's sprite to the adequate one. And redo.
How am I suppose to do that?
my trait class is as below:
[Serializable]
public class Trait
{
public string NameLocalizationKey;
public string DescriptionLocalizationKey;
public string[] IncompatibleTraitLocalizationKey;
public StatName Stat1AffectedName;
public int Stat1AffectedValue;
public TraitStatEffectUnit Stat1AffectedUnit;
public StatName Stat2AffectedName;
public int Stat2AffectedValue;
public TraitStatEffectUnit Stat2AffectedUnit;
public TraitCondition Condition;
public bool StartingTrait;
public bool IsNegative;
public bool AffectStat;
}
NameLocalizationKey is always like that: trait_name_trait1, trait_name_trait2 etc.. and value are stored into a GameData.json
And my traitAsset class is like that:
public class TraitAssets : MonoBehaviour
{
public static TraitAssets Instance { get; private set; }
private void Awake()
{
Instance = this;
}
public Sprite spendthriftySprite;
public Sprite thriftySprite;
public Sprite studiousSprite;
public Sprite lazySprite;
}
I found an online tutorial and did that:
public Sprite GetTraitSprite(string NameLocalizationKey)
{
switch (NameLocalizationKey)
{
default:
case "trait_name_lazy": return TraitAssets.Instance.lazySprite;
case "trait_name_spendthrifty": return TraitAssets.Instance.spendthriftySprite;
case "trait_name_studious": return TraitAssets.Instance.studiousSprite;
case "trait_name_thrifty": return TraitAssets.Instance.thriftySprite;
}
}
I am really new to Unity and I try to figure out what my dev (who abandoned me due to lack of motivation but did an incredible job so far) have done.
Sorry for my unclear formulation and thanks for your answer.
Instead of a "all done result" or answer, if one could explain me step by step how to achieve what I asked that would be marvelously kind. If you give a hungry man a fish, you feed him for a day, but if you teach him how to fish, you feed him for a lifetime.
Im not quite sure what the vision of this implementation is, since there are a few ways to do this vague idea. Seems like that code right there is doing what its supposed to, so i dont see the problem. Call the function to get the sprites and instantiate them.
I reckon that I need first to load the selected NPC trait list, get one trait, instantiate it as GameObject then change it's sprite to the adequate one. And redo.
How am I suppose to do that?:(
Given this exact question, i say just make a new function somewhere (im not familiar with your project) and in it have a for loop that goes through the Traits List and calls that GetTraitSprite function to get it. Then use the unity Instantiate function to spawn it in. To spawn it in game (im assuming you display the sprites onto the unity UI canvas), first create a GameObject prefab in the editor that just holds a sprite component. Spawn in that placeholder with the instantiate. Then in the loop at run time, assign that components sprite to the one GetTraitSprite returns after you've spawned in the template prefab. You could also put an if condition to check the sprite is != null or skip it. The unity Instantiate function returns the spawned gameobject, so you can do whatever you like with it then.
iam pretty new in C# and Unity and facing currently following issue in my game project.
Ive a class to instantiate for various shops each shop makes a different profit has a different name and coasts different power recourses. So my idea is to have a class to make those shops and on constructor call e.g shop creation it should change variables of another script where the balance, power, and so on is calculated here the example code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Shops
{
public int shopID;
public string shopName;
public float shopPower;
public double shopCoast;
public string shopType;
public double shopProfit;
public Shops(int id, string name, float power, double coast, string type, double profit)
{
this.shopID = id;
this.shopName = name;
this.shopPower = power;
this.shopCoast = coast;
this.shopType = type;
this.shopProfit = profit;
Debug.Log("Shop created");
addProfit(profit);
subPower(power);
subCoast(coast);
}
public void addProfit(double profit)
{
}
public void subPower(float power)
{
}
public void subCoast(double coast)
{
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Calculations : MonoBehaviour
{
public double money;
public float power;
public double profitPerHour, coastPerHour, totalPerHour;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
Is it correct or lets say common the way ive written it and that the constructor calls a few methods on call? And how can i accsess the variable double money from the Calculations : Monobeheivor script without the script being attached to a game object? Is there a way without attaching it to a gameobject or not? My idea is that the calculation script does all the calculations needed and iam just grabing the values for my UI from this script. Or wont the update() and start function work?
And one more Question
How can i store all created classobjects in a list or array so that i can print it later in a table where its sorted for example from lowest to highest profit. What is better to use an array or a list?
I hope i made my question clear and thank you in advance.
Like #Ben Rubin said in his comment, it is not a good idea to do another things than initialization of variables in the constructor. But you could do a method eg. Init() which will calls the methods on other classes.
If you have a calculation instance for each shop, then maybe you should merge the 2 classes in only one.
However, if your calculation is global for all the shops, you could make it singleton, without having to make it a MonoBehaviour. And inside you register your shops in a list where you can then access later inside the Calculations class.
public class Shop
{
...
public Shop(...)
{
// initialize only your variables
}
public void Init()
{
Calculations.Instance.RegisterShop(this, true);
// Do your calls to other classes here
}
public void Clear()
{
Calculations.Instance.RegisterShop(this, false);
}
...
}
public class Calculations
{
private static Calculations m_instance = null;
public static Calculations Instance { // singleton
get {
if(m_instance == null)
m_instance = new Calculations();
return m_instance;
}
}
private List<Shop> shopList = new List<Shop>();
public RegisterShop(Shop shop, bool register)
{
bool isRegistered = shopList.Contains(shop);
if(register && !isRegistered)
shopList.Add(shop);
else if(!register && isRegistered)
shopList.Remove(shop);
}
...
}
And for exemple in a script ShopSeller, attached to a GameObject in your scene (I don't know if you do something like that)
public class ShopSeller : MonoBehaviour
{
private Shop shop = null;
public void Start()
{
shop = new Shop(...);
shop.Init();
}
public void OnDestroy()
{
shop?.Clear();
}
...
}
Note that singleton needs to be used wisely, it is not the answer for all difficulties you encounter. It is the only way I can think of for you to not make a MonoBehaviour and attach it to a GameObject to use it.
For your bonus question, you could refer to this chart if you want to choose an appropriate container for what you want to do.
It uses the C++ container types, but it remain the same with some translations to C# :
vector = List
list = LinkedList
map = Dictionary
set = HashSet
deque = no equivalent in C#
The only things it lacks is the basic array, it is useful when you know exactly the length, and you know it will never grow or shrink during runtime.
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);
So I have a bunch of functions that I use OVER AND OVER again all over the place in random areas. And also some getters and setters.
For example just stuff like this:
public GameObject GameObjectCache
{
get
{
if (gameObjectCache == null)
gameObjectCache = this.gameObject;
return gameObjectCache;
}
}
private GameObject gameObjectCache;
public Transform TransformCache
{
get
{
if (transformCache == null)
transformCache = this.GetComponent<Transform>();
return transformCache;
}
}
private Transform transformCache;
This is for Unity if you can't tell.
What I would really like to do is take those functions and put them somewhere else. Then in my classes just do like
[TransformCache]
Some kind of one line tag and it would place the function, from elsewhere, inline into my class.
I know there is some complex way to do this with Mono.Cecil, which if anyone has a simple tutorial on that I'd love the link.
But is there an easier way than that? I know C and Objective-C, and even CG code have functions to do this. Is there anyway to do this in C# with ease?
I don't know if this will help you or not, but how about wrapping some of these common things you want into a wrapper class, then just add the class to your other game object. Something like
public class MyWrapper
{
private GameObject parentGameObj;
public MyWrapper(GameObject srcObj)
{
parentGameObj = srcObj;
}
public GameObject GameObjectCache
{
get
{
if (gameObjectCache == null)
gameObjectCache = parentGameObj.gameObject;
return gameObjectCache;
}
}
private GameObject gameObjectCache;
public Transform TransformCache
{
get
{
if (transformCache == null)
transformCache = parentGameObj.GetComponent<Transform>();
return transformCache;
}
}
private Transform transformCache;
}
Then, in your classes that you will be using it
public class YourOtherClass : GameObject
{
MyWrapper mywrapper;
public Start()
{
// instantiate the wrapper object with the game object as the basis
myWrapper = new MyWrapper(this);
// then you can get the game and transform cache objects via
GameObject cache1 = myWrapper.GameObjectCache;
Transform tcache1 = myWrapper.TransformCache;
}
}
Sorry... in C++ you can derive from multiple classes which in essence COULD allow something like that. The only other thing I can think of is looking into using Generics if your functions use repeated similar types via GetComponent() calls.