Am I having Variable Scope issues? - c#

I am writing in Unity and not all classes can be instantiated as they inheriting Monobehaviour. I have several classes and am trying to Return an array to one class, but keep getting a null reference exception.
I have made sure the array is indexed and initialized, yet it returns null.
However in a same construction without an array, eg an Int, it works.
public class StartUp : MonoBehaviour //Unity class
{
public int x = 30,y = 30;
public PlayField entireField;
void Awake()
{
entireField = new PlayField(x,y);
entireField.InitArray(entireField, x, y);
}
}
public class CharacterController : MonoBehaviour
{
//edit: playField is not supposed hold value, just to get
//access to a method in PlayField
PlayField playField;
FieldData fData;
void Start(){
playField = new PlayField();
fData = new FieldData();
}
void Update(){
fData = playField.GetFieldData(5,6); //We're just telling it go to that method
}
}
public class PlayField
{
public SingleField[,] singleField;
public PlayField()
{
}
public PlayField(int x, int y)
{
singleField = new SingleField[x,y];
}
void InitArray(PlayField playfield, int x, int y){
//In an effort to save the data I also did
this.singleField = new SingleField[x,y];
for(int j ...
{
for (int x...
{
playfield.singleField[x, y] = new SingleField();
playfield.singleField[x, y].fielData = new FieldData();
playfield.singleField[x, y].fielData.height = GetRandom();
//and here
this.singleField[x,y] = new SingleField();
this.singleField[x,y].fieldData = new FieldData();
}
}
//to ..
this.singleField = playfield.singleField;
}
public FieldData GetFieldData(int x, int y){
//Here it keeps returning null reference
return this.singleField[x,y].fieldData;
}
}
public class SingleField
{
public FieldData fieldData;
public GameObject fieldObject;
}
public class FieldData
{
public float height;
public Vector3 position = new Vector3();
}
I know I can use a static variable but I'd like to know what I am doing wrong here or how I can get the values from entireField in StartUp class to the FieldData fData in CharacterController using the none-MonoBehaviour class PlayField?
I thought the this.singleField-array would have values, but not during the Method call from CharacterController?

Erkan, I think you're going to need to take a step back and rethink how you're approaching this. Here's why I say that:
//edit: playField is not supposed hold value, just to get
//access to a method in PlayField
PlayField playField;
... that's not how things work. If you've got a 'main' PlayField that holds all your values, and initialize another one ... any time you call functions on that second one, it'll use the values from the second one. In your case, you're trying to call the GetFieldData function, which will grab field data from the second instance of PlayField - not the one you're going for.
So Where Do You Go From Here?
First, you might want to brush up a bit on Object Oriented Programming concepts. I'm not trying to be condescending - but it'll be hard to continue on with your program if you don't have a decent grasp on them.
Second, consider the use of 'static'. Static says, "I only have one instance of this throughout my program". Take the following for example:
class Playfield
{ /* code */ }
class SomeAlreadyExistingMainClassInYourCode
{
static Playfield globalFieldInstance = new Playfield();
/* rest of the class */
}
... at this point, you've got a single Playfield that's accessible throughout your program: SomeAlreadyExistingMainClassInYourCode.globalFieldInstance.
You shouldn't overuse/abuse this - but if you're only intending on having a single instance of an object being created, creating a static instance of it is a good way to do.

#m.rogalski Yes I was trying to avoid using a static too that's how this started.
Have solved the nullreference error. Really didn't think I had to initialize everything when I just wanted to use it only to call a method* in another class and use another instance of the same class for Return.
public class CharacterController : MonoBehaviour
{
//edit: playField is not supposed hold value, just to get
//access to a method in PlayField
PlayField playField;
FieldData fData;
void Start(){
playField = new PlayField();
InitArray(playField,30,30);
fData = new FieldData();
}
void InitArray(PlayField playfield int x, int y){
playfield.singleField = new SingleField[x,y];
for (int j =0; j< y;.. {
for (int i.. {
playfield.singleField[x,y] = new SingleField();
playfield.singleField[x,y].fieldData = new FieldData();
}
}
}
void Update(){
//The return was not supposed to be a field in this instance of
//PlayField, but come from the PlayField class itself as
//this.singleField[x,y] (a array in PlayField)
fData = playField.GetFieldData(5,6); //We're just telling it go to that method
}
}
public class PlayField
{
public SingleField[,] singleField = new SingleField[30,30];//evrything initailized and so on in the rest of the class here ommited. ect.
public FieldData GetFieldData(int x,int y){
//Here was the catch. Return values form this Class
// and not read from the instance created in CharacterController
//was giving me a nullrefence while I was using only FieldData
return this.singleField[x,y].fieldData;
}
}
This is solved for me.
On to the next question.
Thanks

Related

Value doesn't change when using a struct in a class

Recently, I found a post on Internet asking this question, I tried to figure out but not sure.
I guess the problem is related with Boxing and Unboxing:
public readonly object counter = new Counter();
This line boxs a Counter onto heap, and counter refers to it.
((Counter)riddle.counter)
This line unboxs the Counter from heap.
Every time data it unboxs from heap is same as origin. Therefore, Line A doesn't affect Line B because they both retrieve from heap and are two different instances of Counter.
Is that right? Sorry for my poor English.
public void WantToKnow()
{
var riddle = new Riddle();
((Counter)riddle.counter).Increment(); // Line A
Console.WriteLine(((Counter)riddle.counter).Count); // Line B
// Why the output is 0?///////////////////
}
struct Counter
{
private int x;
public void Increment() { this.x++; }
public int Count { get { return this.x; } }
}
class Riddle
{
public readonly object counter = new Counter();
}
Firstly, this is all a good example of why I try to avoid mutable structs in almost all cases. While you can usually predict what will happen if you pay enough attention, it's easy to miss one copy along the way which messes everything up. If you keep all structs immutable, life is simpler.
For your question: yes, you're unboxing which creates a copy of the counter. Changing that copy doesn't affect anything else. (There's IL to unbox without copying, but C# never uses that.)
You can make this work by making your counter implement an interface with an Increment operation. At that point you can cast to the interface instead of the value type, which means it's not unboxing. Your Increment operation would then modify the value within the box, which means you can then get at it again. Here's a complete example:
using System;
class Program
{
static void Main()
{
var riddle = new Riddle();
((ICounter)riddle.counter).Increment();
Console.WriteLine(((Counter)riddle.counter).Count); // Line B
}
}
interface ICounter
{
void Increment();
}
struct Counter : ICounter
{
private int x;
public void Increment() { this.x++; }
public int Count { get { return this.x; } }
}
class Riddle
{
public readonly object counter = new Counter();
}
Because struct is value type- You can use "class Counter instead "struct Counter"
or use below solution
Reason : ((Counter)riddle.counter).Count is treat as another copy of struct not as ref type. so it's showing initial value 0
using System;
using System.Text.RegularExpressions;
public class Program
{
public static void Main()
{
var riddle = new Riddle();
Console.WriteLine(((Counter)riddle.counter).Increment());
///////////////////////////////////////////
Console.WriteLine(((Counter)riddle.counter).Count);
// Why the output is 0?///////////////////
}
}
struct Counter
{
private int x;
//Change is here
public int Increment() { this.x++; return this.x; }
public int Count { get { return this.x; } }
}
class Riddle
{
public readonly object counter = new Counter();
}

Access object of a class from other classes

I realise this is probably a very simple question and will be answered in no time. But wondering what to do. I have a class called Budget with an object named 'user01' I would basically like to be able to access that object across multiple classes, similar to the code below.
Main
static void Main(string[] args)
{
Budget user01 = new Budget(1000);
}
Budget Class
class Budget
{
private int _budget;
public Budget(int budget)
{
_budget = budget;
}
public int UserBudget
{
get { return _budget; }
set { _budget = value; }
}
}
Expense Class
class Expenses
{
// What I've been trying to do...
public int Something(user01.budget)
{
user01.budget - 100;
return user01.budget;
}
}
I'm not really sure where to go from here, and am hoping to a little help/explanation. Many thanks
This is invalid:
public int Something(user01.budget)
But you can supply an instance of a Budget object to that method:
public int Something(Budget budget)
{
budget.UserBudget -= 100;
return budget.UserBudget;
}
Then you can invoke that method from your consuming code:
Budget user01 = new Budget(1000);
Expenses myExpenses = new Expenses();
int updatedBudget = myExpenses.Something(user01);
The method doesn't "access the variable user01". However, when you call the method, you supply it with your user01 instance. Inside of the method, the supplied instance in this case is referenced by the local budget variable. Any time you call the method and give it any instance of a Budget, for that one time that instance will be referenced by that local variable.
Go ahead and step through this using your debugger and you should get a much clearer picture of what's going on when you call a method.
(Note that your naming here is a bit unintuitive, which is probably adding to the confusion. Is your object a "budget" or is it a "user"? Clearly defining and naming your types and variables goes a long way to making code easier to write.)
Its a pretty simple change to your Expenses class:
class Expenses
{
// What I've been trying to do...
public int Something(Budget userBudget)
{
userBudget.UserBudget -= 100;
return userBudget.UserBudget;
}
}
Which you then call like this from your main class:
static void Main(string[] args)
{
Budget user01 = new Budget(1000);
Expenses expenses = new Expenses();
var result = expenses.Something(user01);
}
Or, if you make your Something method static you can call it without an instance:
class Expenses
{
// What I've been trying to do...
public static int Something(Budget userBudget)
{
userBudget.UserBudget -= 100;
return userBudget.UserBudget;
}
}
Which you call like this:
static void Main(string[] args)
{
Budget user01 = new Budget(1000);
var result = Expenses.Something(user01);
}
Its important when designing methods to remember that a method takes in a general argument and its the caller that passes in something specific.

Lists of Classes with a List - Object reference not set to an instance of an object

I have a problem to determine where my failure is. I think it has something to do with my list in a list ... but I am not sure.
Class:
public class ChunkTerrainData
{
public int OriginX;
public int OriginZ;
public string ChunkMaterialData;
public int[,] ChunkHeightmap;
public string[,] ChunkInventory;
public List<GameObject> InventoryGameObjects;
}
Code Problem:
public static List<ChunkTerrainData> ListOfChunks = new List<ChunkTerrainData>();
//Start()
ChunkData = GenerateTerrain(ThisChunkOriginX, ThisChunkOriginZ, WithChunkData);
ListOfChunks.Add(ChunkData);
//Update()
GameObject Tree;
Tree = (GameObject)Instantiate(Tree_a, InstatiateTreeStone_Position, InstatiateTreeStone_Rotation);
Tree.transform.parent = TerrainMesh.transform;
ListOfChunks[i].InventoryGameObjects.Add(Tree); //some ListOfChunks
at This last line I get a Error (but the transform works well):
NullReferenceException: Object reference not set to an instance of an object
I could also not do (as I get the same error):
Debug.Log(ListOfChunks[i].InventoryGameObjects.Count);
what works (with the same List):
Debug.Log(ListOfChunks.Count);
how can I store and access this type of a list in a List? afaik the assignement of "Tree" is ok (the Cast from Object to GameObject). Can you tell me what to do? :)
Edit: maybe it has something to do with this List Initialisation - but I have no clue how to do it in C#
You never initialize your InventoryGameObjects field. Here is how it should look:
public static List<ChunkTerrainData> ListOfChunks = new List<ChunkTerrainData>();
//Start()
ChunkData = GenerateTerrain(ThisChunkOriginX, ThisChunkOriginZ, WithChunkData);
ChunkData.InventoryGameObjects = new List<GameObject>();
ListOfChunks.Add(ChunkData);
//Update()
GameObject Tree = (GameObject)Instantiate(Tree_a, InstatiateTreeStone_Position, InstatiateTreeStone_Rotation);
Tree.transform.parent = TerrainMesh.transform;
ListOfChunks[i].InventoryGameObjects.Add(Tree); //some ListOfChunks
Give that a try.
The Answer as supposed was:
//...
ChunkData = GenerateTerrain(ThisChunkOriginX, ThisChunkOriginZ, WithChunkData);
ListOfChunks.Add(ChunkData);
ListOfChunks[ListOfChunks.Count - 1].InventoryGameObjects = new List<GameObject>();
// ...

Trying to setup a BlackJackTable, trouble with setting up my OO design

I'm trying to build a console app that is a blackjack game. BlackJackTable : TableGame and has 6 BettingSpots. I'm thinking I want to have an array that contains the BettingSpots. But I am getting errors trying to populate the BettingSpot[]. Any advice on how to better proceed with the design would be much appreciated.
public abstract class TableGame
{
// Can have 5-7 bettings spots. Has a dealer, players, Rules
public abstract void Rules();
public abstract BettingSpot[] bettingSpotArray;
public Dealer dealer = new Dealer();
}
public class BlackJackTable : TableGame
{
// A blackjack tablegame "has a" 6 BettingSpots available that a Player chooses to occupy. Have the Game ask the player which bettingspots they'd
// like to place a bet on. Bet amount must be the same for each. Use a try catch block to make sure TotalChips >= all bets.
public BlackJackTable(int tableNumber)
{
_tableNumber = tableNumber;
}
public override void BlackJackRules()
{ }
BettingSpot spot1 = new BettingSpot(1);
BettingSpot spot2 = new BettingSpot(2);
BettingSpot spot3 = new BettingSpot(3);
BettingSpot spot4 = new BettingSpot(4);
BettingSpot spot5 = new BettingSpot(5);
BettingSpot spot6 = new BettingSpot(6);
public override BettingSpot[] bettingSpotArray = new BettingSpot[5];
for (int i = 0; i < bettingSpotArray.Length; i++)
{
bettingSpotArray[i] = new BettingSpot[i+1];
}
public void QueryPlayerForBettingSpots(BettingSpot[] bettingSpotArray)
{
int[] BettingSpotsAvailable = new BettingSpot[5];
for (int idx = 0; idx < 5; idx++)
if (bettingSpotArray[idx] == 0)
BettingSpotsAvailable[idx]
Console.WriteLine("Place up to 3 bets on the following available BettingSpots: {0}", bettingSpotArray.Where<BettingSpot.
}
}
public class BettingSpot
{
protected decimal bet = 0;
public int _bettingSpotNumber;
// How many spots are on the Blackjack table will determine how many seats there will be. There are six betting spots allowed,
// so six bettingspots are created. THere are just 6 BettingSpots available and a player can
// occupy up to 3 BettingSpots at a time. A bettingspot "has a" bet. If no bet, put '0' in BettingSpotArray
public BettingSpot(int number)
{
_bettingSpotNumber = number;
}
public Player player
public decimal Bet
{
get
{
return bet;
}
set
{
bet = value;
}
}
A few things I noticed in your code.
First, I believe you're having trouble trying to populate bettingSpotArray[] because you're trying to do it inside the body of the class. You need to do it inside the body of a method or property - I'd suggest the constructor or the Rules() method.
Secondly, since you're not defining any code in the abstract class, you might find it easier to make the abstract class an interface and have your game classes implement the interface - that way the class will know what it has to implement, but you don't have to override everything. If you had some sort of default logic you wanted for a majority of the game classes, then I'd agree with using an abstract class that had that base logic, and the "special" classes would override it as needed. But that's just my take on it; you may have your own valid reasons for using an abstract class that are not readily apparent in your question.
I'm not sure the code you have posted will actually compile, but I'll give some code samples that should help you get to where you're trying to go.
public class BlackJackTable : TableGame
{
// If other classes need access to this I'd set it up as public
// property, not a public field. If not, I'd set the field to
// private
public override BettingSpot[] bettingSpotArray = new BettingSpot[5];
public BlackJackTable(int tableNumber)
{
// I don't see a _tableNumber field in your abstract class or your
// inheriting class - if you don't have that field you'll get an error
// in the compiler
_tableNumber = tableNumber;
}
// Your posted code had public override void BlackJackRules, but there is
// no BlackJackRules() method to override
public override void Rules()
{
// These are superfulous since you'll be using an array
// for the betting spots
//BettingSpot spot1 = new BettingSpot(1);
//BettingSpot spot2 = new BettingSpot(2);
//BettingSpot spot3 = new BettingSpot(3);
//BettingSpot spot4 = new BettingSpot(4);
//BettingSpot spot5 = new BettingSpot(5);
//BettingSpot spot6 = new BettingSpot(6);
// Now you can initialize your array
for (int i = 0; i < bettingSpotArray.Length; i++)
{
bettingSpotArray[i] = new BettingSpot[i+1];
}
}
}
Your QueryPlayerForBettingSpots doesn't make a lot of sense either, as it prompts for input from the user, but doesn't accept any input. Perhaps you haven't finished that method?
I think your overall approach is the correct approach, but your implementation has some issues (which I've noted above). Hopefully this will be of some help to you in moving forward in your project.

Returning variables from public class C#

I have the following code
public class IDFMeasure
{
,,,,,,,,,,
........
public float [][] GetIDFMeasure(string[] documents)
{
_docs = documents;
_numDocs = documents.Length;
MyInit();
return _termWeight;
}
}
I want to call this class in the main program. How I do it ? I'm getting confused with class types.. Can any help please? Many thanks
You don't call a class. You instantiate a class and call its methods. You can do so like this:
public void main() {
IDFMeasure measure = new IDFMeasure(); // instantiate class
float[][] vals = measure.GetIDFMeasure(documents); // now call method on that class
}
Create object of class and then call the method.
IDFMeasure obj = new IDFMeasure ();
float [][] arr = obj.GetIDFMeasure(new string[]{"1"});
If you only need to call the method and do not need object any more then you can create anonymous object and call method on it.
float [][] arr = new IDFMeasure().GetIDFMeasure(new string[]{"1"});

Categories