Can't create Object C# [duplicate] - c#

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
I got 2 same classes, one for the primary weapon and the other for the secondary one. Here are my classes :
public class weapon : MonoBehaviour {
public string Name { get; set; }
public float Damages { get; set; }
public float FireRate { get; set; }
public float Range { get; set; }
public float BulletSpeed { get; set; }
public bool isOn { get; set; }
public weapon(string name, float damages, float fireRate, float range, float bulletSpeed, bool ison) {
this.Name = name;
this.Damages = damages;
this.FireRate = fireRate;
this.Range = range;
this.BulletSpeed = bulletSpeed;
this.isOn = ison;
}
}
public class weapon1 : MonoBehaviour {
public string Name { get; set; }
public float Damages { get; set; }
public float FireRate { get; set; }
public float Range { get; set; }
public float BulletSpeed { get; set; }
public bool isOn { get; set; }
public weapon1(string name, float damages, float fireRate, float range, float bulletSpeed, bool ison) {
this.Name = name;
this.Damages = damages;
this.FireRate = fireRate;
this.Range = range;
this.BulletSpeed = bulletSpeed;
this.isOn = ison;
}
}
I want in another script that when I press 'F', the weapons take respectively their specs, but it gets stuck at giving the name to the second one, here is my script to give them their specs:
void Update () {
if (Input.GetKeyDown (KeyCode.F)) {
GetComponent<weapon> ().Name = "Rien";
GetComponent<weapon> ().Damages = 0;
GetComponent<weapon> ().FireRate = 0;
GetComponent<weapon> ().Range = 0;
GetComponent<weapon> ().BulletSpeed = 0;
GetComponent<weapon> ().isOn = true;
Debug.Log (GetComponent<weapon> ().Name);
GetComponent<weapon1> ().Name = "Rien1"; //stuck here... :'(
GetComponent<weapon1> ().Damages = 0;
GetComponent<weapon1> ().FireRate = 0;
GetComponent<weapon1> ().Range = 0;
GetComponent<weapon1> ().BulletSpeed = 0;
GetComponent<weapon1> ().isOn = false;
Debug.Log(GetComponent<weapon1> ().Name);
}
}
I'm getting 'Object reference not set to an instance of an object' and I did exactly the same thing for both weapons
Thanks in advance

You are making some basic programming errors as well as some basic Unity specific errors. As said in the comments, you shouldn't have lots of classes that are exactly the same. Remember to not repeat your self.
Then you are inheriting from MonoBehaviour but are defining a constructor method to set your fields. Don't do this in unity. Make the feilds available in the inspector by making them public or adding the [SerializeField] attribute to private member variables. If you have anything you want to do when the object is created then put this in the Start() method:
public Weapon : MonoBehviour
{
public string name; //set these in the inspector for each weapon
public float damage;
//etc
// in Unity you use the Start method for mono behaviours. NOT the constructor method
void Start()
{
//Do things when the object is created
}
}
Now, it's not clear how you are adding weapons to your player from your question but what you should do is add a game object as a child to the player object in the hierarchy. Do this for each weapon and then add your weapon script to each weapon. Then change the fields that you made available to yourself in the inspector. You can then get a reference to the weapons that the player currently has via a script on the player and do as you please with their values when you press a key.

Related

My awake function is not initializing, so a NullReferenceException is coming up

I was working on a xml saving system for my game but whenever I instantiate my prefab all of my public transforms, animators etc have gone null. I found this out by going into debug mode and looking into my player script. in my create actor function in my Game controller script I have created a player movement state machine script from a video series I watched. Inside it has all of the states, animations etc.
Here is my Player script code:
using UnityEngine;
using Cinemachine;
namespace GenshinImpactMovementSystem
{
[RequireComponent(typeof(PlayerInput))]
[RequireComponent(typeof(PlayerResizableCapsuleCollider))]
public class Player : MonoBehaviour
{
[field: Header("References")]
[field: SerializeField] public PlayerSO Data { get; private set; }
[field: Header("Collisions")]
[field: SerializeField] public PlayerLayerData LayerData { get; private set; }
[field: Header("Camera")]
[field: SerializeField] public PlayerCameraRecenteringUtility CameraRecenteringUtility { get; set; }
[field: Header("Animations")]
[field: SerializeField] public PlayerAnimationData AnimationData { get; private set; }
public Rigidbody Rigidbody { get; private set; }
public Animator Animator { get; private set; }
public PlayerInput Input { get; private set; }
public PlayerResizableCapsuleCollider ResizableCapsuleCollider { get; private set; }
public Transform MainCameraTransform { get; private set; }
public PlayerMovementStateMachine movementStateMachine;
public IKController IKController;
public Transform cameraPointLookAt;
public CinemachineVirtualCamera cam;
private void Awake()
{
CameraRecenteringUtility.Initialize();
AnimationData.Initialize();
Rigidbody = GetComponent<Rigidbody>();
Animator = GetComponentInChildren<Animator>();
Input = GetComponent<PlayerInput>();
ResizableCapsuleCollider = GetComponent<PlayerResizableCapsuleCollider>();
MainCameraTransform = Camera.main.transform;
movementStateMachine = new PlayerMovementStateMachine(this);
}
private void Start()
{
movementStateMachine.ChangeState(movementStateMachine.IdlingState);
}
private void Update()
{
movementStateMachine.HandleInput();
movementStateMachine.Update();
}
private void FixedUpdate()
{
movementStateMachine.PhysicsUpdate();
}
private void OnTriggerEnter(Collider collider)
{
movementStateMachine.OnTriggerEnter(collider);
}
private void OnTriggerExit(Collider collider)
{
movementStateMachine.OnTriggerExit(collider);
}
public void OnMovementStateAnimationEnterEvent()
{
movementStateMachine.OnAnimationEnterEvent();
}
public void OnMovementStateAnimationExitEvent()
{
movementStateMachine.OnAnimationExitEvent();
}
public void OnMovementStateAnimationTransitionEvent()
{
movementStateMachine.OnAnimationTransitionEvent();
}
}
}
Here is my Game Controller code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Cinemachine;
using TMPro;
namespace GenshinImpactMovementSystem
{
public class GameController : MonoBehaviour
{
public Button saveButton;
public Button loadButton;
public CinemachineVirtualCamera camera;
public const string playerPath = "Prefabs/Player";
private static string dataPath = string.Empty;
void Awake()
{
if (Application.platform == RuntimePlatform.IPhonePlayer)
{
dataPath = System.IO.Path.Combine(Application.persistentDataPath, "Resources/actors.xml");
}
else
{
dataPath = System.IO.Path.Combine(Application.dataPath, "Resources/actors.xml");
}
}
void Start()
{
CreateActor(playerPath, new Vector3(0, 0, 0), Quaternion.identity);
}
public static Actor CreateActor(string path, Vector3 position, Quaternion rotation)
{
GameObject prefab = Resources.Load<GameObject>(path);
GameObject go = GameObject.Instantiate(prefab, position, rotation) as GameObject;
Player playerScript = go.GetComponent<Player>();
Transform cameraLookAt = playerScript.cameraPointLookAt;
CinemachineVirtualCamera cam = FindObjectOfType<CinemachineVirtualCamera>();
cam.Follow = cameraLookAt;
cam.LookAt = cameraLookAt;
playerScript.CameraRecenteringUtility.VirtualCamera = cam;
Actor actor = go.GetComponent<Actor>() ?? go.AddComponent<Actor>();
return actor;
}
public static Actor CreateActor(ActorData data, string path, Vector3 position, Quaternion rotation)
{
GameObject prefab = Resources.Load<GameObject>(path);
GameObject go = GameObject.Instantiate(prefab, position, rotation);
Actor actor = go.GetComponent<Actor>() ?? go.AddComponent<Actor>();
actor.data = data;
return actor;
}
void OnEnable()
{
saveButton.onClick.AddListener(delegate {SaveData.Save(dataPath, SaveData.actorContainer);});
loadButton.onClick.AddListener(delegate {SaveData.Load(dataPath);});
}
void OnDisable()
{
saveButton.onClick.RemoveListener(delegate {SaveData.Save(dataPath, SaveData.actorContainer);});
loadButton.onClick.RemoveListener(delegate {SaveData.Load(dataPath);});
}
}
}
I thought I would show you the player camera recentering utility script because there is an error there also:
using Cinemachine;
using System;
using UnityEngine;
namespace GenshinImpactMovementSystem
{
[Serializable]
public class PlayerCameraRecenteringUtility
{
[field: SerializeField] public CinemachineVirtualCamera VirtualCamera { get; set; }
[field: SerializeField] public float DefaultHorizontalWaitTime { get; private set; } = 0f;
[field: SerializeField] public float DefaultHorizontalRecenteringTime { get; private set; } = 4f;
private CinemachinePOV cinemachinePOV;
public void Initialize()
{
cinemachinePOV = VirtualCamera.GetCinemachineComponent<CinemachinePOV>();
}
public void EnableRecentering(float waitTime = -1f, float recenteringTime = -1f, float baseMovementSpeed = 1f, float movementSpeed = 1f)
{
cinemachinePOV.m_HorizontalRecentering.m_enabled = true;
cinemachinePOV.m_HorizontalRecentering.CancelRecentering();
if (waitTime == -1f)
{
waitTime = DefaultHorizontalWaitTime;
}
if (recenteringTime == -1f)
{
recenteringTime = DefaultHorizontalRecenteringTime;
}
recenteringTime = recenteringTime * baseMovementSpeed / movementSpeed;
cinemachinePOV.m_HorizontalRecentering.m_WaitTime = waitTime;
cinemachinePOV.m_HorizontalRecentering.m_RecenteringTime = recenteringTime;
}
public void DisableRecentering()
{
cinemachinePOV.m_HorizontalRecentering.m_enabled = false;
}
}
}

Check if instance of class exists with certain property

I have a list of classes, each with four properties:
public class BroncoClass
{
public NPC npc { get; set; }
public int TimeLeft { get; set; }
public bool Gravity { get; set; }
public bool Rotation { get; set; }
}
public List<BroncoClass> BroncoList = new List<BroncoClass>();
I want to check if the list contains a class with a specific npc value, for example:
for (int i = 0; i < Main.npc.Length; i++) // For every alive npc
{
if(BroncoList.contains a class where npc == Main.npc[i])
{
}
}
Haven't been able to find an answer online, any help is appreciated.
The real solution is to just keep a collection somewhere and use LINQ to query it. Presumably this collection would be easy to maintain as it would be the collection that is used for all other operations with BroncoClass.
After update to OP...
You already have the list, just use list.Any(o => o.npc == testNpc) or whatever other predicate you may need.
However, if you really want to do the actual question:
Sounds like a reasonable usage of a factory pattern; but you will need to effectively do manual memory management. Your factory would be something like:
// Could be static, but I hate static. Don't use static.
public class BroncoFactory
{
private List<BroncoClass> trackedObjects = new List<BroncoClass>();
public BroncoClass New()
{
var newInstance = new BroncoClass();
trackedObjects.Add(newInstance)
}
// Don't forget to call this or you'll leak!
public void Free(BroncoClass instance)
{
trackedObjects.Remove(instance);
}
public bool ExistsWithNPC(NPC test)
{
return trackedObjects.Any(o => o.npc == test);
}
}
Just really, really don't forget to call Free on an object when you are done with it.
Very similar to #BradleyDotNET's answer. I just folded the factory into the class as static methods. I'm not saying this is right way to go, I'm just offering it as a solution to your question. Using static methods in the class seems closer to what the OP is asking about.
First, I needed an NPC class to get this to compile. Notice that it implements IEquatable so that I can compare instances for equality the way I want to (and that I override GetHashCode because that's a requirement).
public class NPC : IEquatable<NPC>
{
private static int _indexKeeper = 0;
public int Index { get; } = _indexKeeper++;
public bool Equals(NPC other)
{
return Index == other?.Index;
}
public override int GetHashCode()
{
return Index.GetHashCode();
}
}
With that, here's the BroncoClass (mostly untested):
public class BroncoClass
{
private BroncoClass(int timeLeft, bool gravity, bool rotation)
{
Npc = new NPC();
TimeLeft = timeLeft;
Gravity = gravity;
Rotation = rotation;
}
public NPC Npc { get; set; }
public int TimeLeft { get; set; }
public bool Gravity { get; set; }
public bool Rotation { get; set; }
private static List<BroncoClass> _instances = new List<BroncoClass>();
public static BroncoClass Create(int timeLeft, bool gravity, bool rotation)
{
var bronco = new BroncoClass(timeLeft, gravity, rotation);
_instances.Add(bronco);
return bronco;
}
public static bool Remove(NPC npc)
{
var broncoFound = _instances.FirstOrDefault(b => b.Npc == npc);
if (broncoFound == null)
{
return false;
}
_instances.Remove(broncoFound);
return true;
}
public static BroncoClass Find(NPC npc)
{
return _instances.FirstOrDefault(b => b.Npc == npc);
}
}

Get all names of property of another class - Unity 5 C#

I created this class called Genes and I want to get all it's properties inside of another script. I tried using
PropertyInfo[] props = typeof(Genes).GetProperties();
but props is an empty array. I think typeof isn't working. This is my class Genes:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Genes
{
private float size;
private float speed;
private float probability;
private int color;
public Genes(float size, float speed, float probability, int color)
{
this.size = size;
this.speed = speed;
this.probability = probability;
this.color = color;
}
}
and I basically want to run over size, speed, probability and color using a foreach loop. What is the problem?
Either make your fields properties which have getters and setters:
public class Genes
{
private float Size { get; set; }
private float Speed { get; set; }
private float Probability { get; set; }
private int Color { get; set; }
public Genes(float size, float speed, float probability, int color)
{
this.Size = size;
this.Speed = speed;
this.Probability = probability;
this.Color = color;
}
}
or use GetFields if you really want fields:
typeof(Genes).GetFields();
No matter what you chose, these members should furthermore either be public, or you have to use the BindingFlags.NonPublic to look for non-public members:
typeof(Genes).GetProperties(BindingFlags.NonPublic);
or
typeof(Genes).GetFields(BindingFlags.NonPublic);

Add custom object to the script

I just cant manage to add a public object to the dcript i have.
There is code:
public class Player : MonoBehaviour {
public string charName = "";
public int currentLevel = 0;
public int experiense = 0;
public int strength = 1;
public int agility = 1;
public int maxHealth = 30;
public float currentHealth = 30;
public int maxActionPoints = 5;
public int currentLevelPoints = 10;}
there is another script where i want to add a public property with this class
public class CharManager : MonoBehaviour {
public GameObject currentCharacter;
public GameObject charMenu;
public Player currentPlayerStats;
public void changeCharacter(GameObject character)
{
if (currentCharacter){
saveCharacter ();
}
currentCharacter = character;
loadSavedInfo ();
}
void loadSavedInfo()
{
string playerJson = "";
if (currentCharacter.tag== "Man")
{
if (File.Exists(Application.persistentDataPath +"/Char1.json"))
{
playerJson = File.ReadAllText(Application.persistentDataPath +"/Char1.json");
}
}
else
{
if (File.Exists(Application.persistentDataPath +"/Char2.json"))
{
playerJson = File.ReadAllText(Application.persistentDataPath +"/Char2.json");
}
}
if (playerJson != string.Empty)
{
Player thePlayer = JsonConvert.DeserializeObject<Player>(playerJson);
currentPlayerStats = thePlayer;
}
else
{
currentPlayerStats = gameObject.AddComponent<Player>() as Player;
}
}
This code add NEW player component and currentPlayerStats have class CharManager... what am i doing wrong?
Any help is very appreciated!
gameObject.AddComponent() adds a MonoBehaviour derived component to the game object. Player does not derive from MonoBehaviour thus it cannot be added
Looks like Player is just a regular class, so you can just create an object of that class
Player currentPlayerStats = new Player();
I figured it out.
Player class must be non MonoBehaviour class. A class where i have to access the player class should have a public property:
public Player thePlayer;
not
public GameObject thePlayer;
Thanks everyone!

Ball Rolling in DirectX with C#

Im trying to create a seesaw with ball on its shape, that based on the shapes angle, the ball rolls.
Here is the screenshot of it.
So, the shape of the seesaw moves based on the angle generatated by a trackbar value.
Here are the variables declared:
private const float ONE_DEGREE = 0.0174532924f;
private ID3DMesh tab;
private ID3DMesh ball;
The 'tab' variable is the shape.
This method sets the angle of the shape:
public void setShapeAngle(float degree)
{
tabTargetAngle = Util.DegreeToRadian(degree);
}
And here is the method that updates it:
public void Update(int elapsedTime)
{
if (tab.Pitch != tabTargetAngle)
{
if (tabTargetAngle > tab.Pitch)
{
if (tab.Pitch >= (tabTargetAngle - ONE_DEGREE))
{
tab.Pitch = tabTargetAngle;
}
else
{
tab.Pitch += tabuaSpeed * elapsedTime;
}
}
else if (tabTargetAngle < tab.Pitch)
{
if (tab.Pitch <= (tabTargetAngle + ONE_DEGREE))
{
tab.Pitch = tabTargetAngle;
}
else
{
tab.Pitch -= tabuaSpeed * elapsedTime;
}
}
}
}
All of the objects, are ID3DMesh objects. Here is the code of the ID3DMesh class.
public interface ID3DMesh : IDisposable
{
Color Ambient { get; set; }
CollisionTestMethod CollisionDetectionMethod { get; set; }
Mesh D3DXMesh { get; }
Color Diffuse { get; set; }
Color Emissive { get; set; }
Material[] Materials { get; set; }
ID3DMesh Parent { get; set; }
float Pitch { get; set; }
Vector3 PivotOffset { get; set; }
float PivotOffsetX { get; set; }
float PivotOffsetY { get; set; }
float PivotOffsetZ { get; set; }
Vector3 Position { get; set; }
RenderOptions RenderSettings { get; set; }
float Roll { get; set; }
Vector3 Scale { get; set; }
float ScaleX { get; set; }
float ScaleY { get; set; }
float ScaleZ { get; set; }
Color Specular { get; set; }
float SpecularSharpness { get; set; }
Texture[] Textures { get; set; }
Color WireColor { get; set; }
float X { get; set; }
float Y { get; set; }
float Yaw { get; set; }
float Z { get; set; }
MeshBoundingBox GetBoundingBox();
MeshBoundingSphere GetBoundingSphere();
float GetDepth();
float GetHeight();
float GetWidth();
Matrix GetWorldMatrix();
bool Intersects(ID3DMesh mesh);
void Link(ID3DMesh parentMesh, Vector3 linkPosition);
void Move(float xAmount, float yAmount, float zAmount);
void Render();
void RenderPlanarShadow(Plane groundPlane, Light light, bool allowDoubleBlending);
void SetDepth(float depth);
void SetDepth(float depth, bool uniformScale);
void SetHeight(float height);
void SetHeight(float height, bool uniformScale);
void SetPlanarShadowOpacity(float shadowOpacity);
void SetScale(float amount);
void SetScale(float xAmount, float yAmount, float zAmount);
void SetSize(float width, float height, float depth);
void SetWidth(float width);
void SetWidth(float width, bool uniformScale);
}
I tried to use the Move(float, float, float) method. But it didnt moved as it should. If you could help me with that.
Thank you.
(Note: Below I'll be ignoring the third dimension, because the ball will always move along the same plane)
If we take the seesaw as a reference frame, I think the movement of the ball will be similar to that of an harmonic oscillator. That is to say, the position of the ball along the seesaw at a given instant of time, s(t), will be given by the following formula:
s(t) = L cos(2π t / T + ϕ)
where L is the length of the seesaw (the amplitude of the harmonic) and T is the time it takes the ball to move from one end of the seesaw to the other and back to the start (the period of the harmonic). ϕ, the initial phase of the harmonic, is there to adjust the formula so s(0) gives you the starting position. If you want it to start at the center, you need to make s(0) = 0, which means you need the cosine to be 0. So you have to make ϕ be π/2 (90 degrees), because cos(π/2) = 0.
With this you can put the ball in place by changing the world transform. If you rotate it to the current angle of the seesaw (let's call it θ(t)), you can just translate the ball by the value of s(t) along the xx axis.
This is equivalent to treating (s(t),θ(t)) as the position of the ball in polar coordinates. You can then get the cartesian coordinates at a given time (x(t),y(t)) with these formulae:
x(t) = s(t) cos(θ)
y(t) = s(t) sin(θ)
(Let's assume the up-vector is (0, 1, 0) and the tab is aligned with the X-axis)
You can imagine the ball would have to "roll" down the tab along the X-axis, and you would have to calculate the Y-position to let it stick to the tab.
You could use the Move() method for the X position, as the ball's speed has an impact on it's X-position in a relative way.
The Y-position though (as long as the ball remains on the tab) could more easily be calculated for each X-position, by setting the Y property.
If I were you I'd start by creating a method that calculates the Y position to make the ball "stick to the tab" for any X position.
If this doesn't point you in the right direction, please elaborate a bit more on "it didnt moved as it should".

Categories