Reply
Thread Tools Display Modes
#1
Old 09-09-2015, 03:59 PM
Guest
Join Date: Sep 2010
Posts: 481
Unity: C# lookup tables

Can anyone explain how to do a lookup table in C#? I'm coming from excel world with vlookups (columns & rows) and am having a hard time replicating in Unity C#. (put this in Game Room b/c I'm doing amateur game programming in Unity)

For example, say I have a list of characters (column A) and a list of attributes (rows B-Z) with integers. If I want to lookup Character A's Charisma in excel, it is trivial with a vlookup/match formula. (e.g. go down until you find Character A, then go over to the Charisma column and return the value)

How do I set up essentially the same operation in C#? I looked at arrays, but they seem just to be a single list. Dictionaries are slightly better with a key pair, but it's only a single pair, whereas I need to have multiple attributes for each character.

All help welcome (even better if in plain English). Thanks!!!
#2
Old 09-09-2015, 06:23 PM
Guest
Join Date: May 2003
Location: NJ
Posts: 8,050
I think you might be shoehorning excel into the problem by thinking of your character as a spread sheet instead of an object.

Your character should simply be an instance of Character with the relevant properties:

Code:
public class Character
{
 public string Name { get; set; }
 public int Charisma { get; set; }
 public int Strength { get; set; }
 ...
 public Character(string name)
 {
 this.Name = name;
 }
}
Then you instantiate your object:

Character Player1 = new Player1("Kinthalis the awesome");

And you get it's properties like so:

int cha = Player1.Charisma;

Now, if you're dealing with a collection of characters, you'd probably place them in a List<Character> (or maybe an array) like so:

List<Character> myCharacters = new List<Character>();

myCharacters.Add(Player1);

etc. you can then iterate on the collection or search that collection for a particular player.

Last edited by Kinthalis; 09-09-2015 at 06:26 PM.
#3
Old 09-09-2015, 06:55 PM
Guest
Join Date: May 2003
Location: NJ
Posts: 8,050
Hastily written, so corrections:

Quote:
Originally Posted by Kinthalis View Post
I think you might be shoehorning excel into the problem by thinking of your character as a spread sheet instead of an object.

Your character should simply be an instance of a "Character" object with the relevant properties:

Code:
public class Character
{
 public string Name { get; set; }
 public int Charisma { get; set; }
 public int Strength { get; set; }
 ...

 public Character(string name)
 {
 this.Name = name;
 }
}
Then you instantiate your object:

Code:
Character Player1 = new Character("Kinthalis the awesome");
And you get/set it's properties like so:

Code:
int cha = Player1.Charisma;

Player1.Strength = 10;
Now, if you're dealing with a collection of characters, you'd probably place them in a List<Character> (or maybe an array) like so:

Code:
List<Character> myCharacters = new List<Character>();

myCharacters.Add(Player1);
myCharacters.Add(Player2);
...
You can then iterate on the collection or search that collection for a particular player:

Code:
foreach(Character char in myCharacters) {
 char.Intelligence += 10;
}

Character kinthalis = myCharacters.Find(c => c.Name == "Kinthalis the Awesome");
#4
Old 09-09-2015, 07:57 PM
Guest
Join Date: May 2003
Location: NJ
Posts: 8,050
It occurred to me that I didn't answer your question

So, if you do need to reference data as you would in a spread sheet, there a few ways to do that.

A staggered array: characters[10][10]

A multidimensional array (matrix): characters[10,10]

A List of Lists: List< List<string> > matrix = new List< List<string> >();

Not sure if unity allows this, but you could also use a DataTable object: https://msdn.microsoft.com/en-us/lib...v=vs.110).aspx
#5
Old 09-09-2015, 08:05 PM
Guest
Join Date: May 2003
Location: NJ
Posts: 8,050
EDIT: so I really hate the 5 minute edit limit... or I suck at using preview. One of those.


So maybe something like this:

string[][] characters = new string[][]
{
/// {name,strength,charisma}
new string[] {"player1","2","4"},
new string[] {"Player2","11","22"}
...
};

And you'd reference player one strength like so: characters[0][1];
#6
Old 09-10-2015, 12:40 AM
Guest
Join Date: Mar 2007
Location: Miskatonic University
Posts: 10,260
Quote:
Originally Posted by Kinthalis View Post
I think you might be shoehorning excel into the problem by thinking of your character as a spread sheet instead of an object.
Note that there is a powerful, in-use game engine paradigm that emulates a database or spreadsheet called an "Entity Component System." (one example) Where different sets of properties are "components" which can be treated like (sometimes empty) columns in a spreadsheet. Unity is partially one already, but actually writing a full-on ECS on top of Unity is non-trivial.

Last edited by Jragon; 09-10-2015 at 12:44 AM.
#7
Old 09-10-2015, 02:35 AM
Member
Join Date: Jun 2000
Location: Los Angeles
Posts: 10,138
If you just need a simple look-up, I'd use an array of structs:

Code:
public struct Character {
public String name; public int strength; public int intelligence; public int wisdom;
} // In the class where you use the data, initialize the array: Character[] characters = new Character[50]; // When you need to access an element, use this syntax: characters[10].strength = 18;
Structs have less overhead than classes. And I prefer arrays over the c++ container classes like List because the container classes sometimes perform inefficient memory manipulations behind the scenes.
#8
Old 09-10-2015, 04:14 AM
Guest
Join Date: Mar 2007
Location: Miskatonic University
Posts: 10,260
Quote:
Originally Posted by The Hamster King View Post
If you just need a simple look-up, I'd use an array of structs:

Code:
public struct Character {
public String name; public int strength; public int intelligence; public int wisdom;
} // In the class where you use the data, initialize the array: Character[] characters = new Character[50]; // When you need to access an element, use this syntax: characters[10].strength = 18;
Structs have less overhead than classes. And I prefer arrays over the c++ container classes like List because the container classes sometimes perform inefficient memory manipulations behind the scenes.
I'm pretty sure List is just a dynamic array, so you can probably avoid any dynamic allocations by allocating a large enough buffer. It does mean every time you add to the list it has to increase an internal counter, but the overhead is generally trivial.

At AAA, professional, or resource-constrained console or embedded game development levels where the programmers are experienced or resources are extremely scarce, it's probably worth worrying about this. But beginner-level indie game dev in Unity is probably not the best place to explore these bottlenecks. At least not until significant profiling hints it's an issue at least. At the beginner level there's likely much lower hanging fruit than worrying about cache locality or dynamic heap allocations.

E: The struct vs class point is more fair, though. If you're just storing data a struct is absolutely appropriate.

Last edited by Jragon; 09-10-2015 at 04:17 AM.
#9
Old 09-10-2015, 07:15 AM
Guest
Join Date: May 2003
Location: NJ
Posts: 8,050
Quote:
Originally Posted by Jragon View Post
Note that there is a powerful, in-use game engine paradigm that emulates a database or spreadsheet called an "Entity Component System." (one example) Where different sets of properties are "components" which can be treated like (sometimes empty) columns in a spreadsheet. Unity is partially one already, but actually writing a full-on ECS on top of Unity is non-trivial.
Hmmm, interesting. I need to take a look. Doesn't sound very testable.

Quote:
Originally Posted by The Hamster King View Post
If you just need a simple look-up, I'd use an array of structs:

Code:
public struct Character {
public String name; public int strength; public int intelligence; public int wisdom;
} // In the class where you use the data, initialize the array: Character[] characters = new Character[50]; // When you need to access an element, use this syntax: characters[10].strength = 18;
Structs have less overhead than classes.
Yep, although I figured he might eventually have the need to add behaviour to his objects like Player1.jump() and he might possibly want to abstract behaviours out to parent classes or interfaces.

Quote:
Originally Posted by Jragon View Post
I'm pretty sure List is just a dynamic array, so you can probably avoid any dynamic allocations by allocating a large enough buffer. It does mean every time you add to the list it has to increase an internal counter, but the overhead is generally trivial.

At AAA, professional, or resource-constrained console or embedded game development levels where the programmers are experienced or resources are extremely scarce, it's probably worth worrying about this. But beginner-level indie game dev in Unity is probably not the best place to explore these bottlenecks. At least not until significant profiling hints it's an issue at least. At the beginner level there's likely much lower hanging fruit than worrying about cache locality or dynamic heap allocations.

E: The struct vs class point is more fair, though. If you're just storing data a struct is absolutely appropriate.
Yep.
#10
Old 09-10-2015, 07:58 AM
Guest
Join Date: Mar 2007
Location: Miskatonic University
Posts: 10,260
Quote:
Originally Posted by Kinthalis View Post
Hmmm, interesting. I need to take a look. Doesn't sound very testable.
It's actually more testable, IMO (and from experience). It makes it relatively trivial to factor out a given component or system, or construct an object without any rendering in its loop or whatever. Theoretically all systems are independent, but in practice that's obviously not true (the positions and orientations the physics component updates has to be read by the renderer at some point, after all), but it means that code one person touches is generally independent of code someone else touches, and you can test most components and systems in a vacuum devoid of other components. Nothing is stopping you from doing integration testing over multiple components, of course.
#11
Old 09-10-2015, 09:27 AM
Guest
Join Date: May 2003
Location: NJ
Posts: 8,050
Quote:
Originally Posted by Jragon View Post
It's actually more testable, IMO (and from experience). It makes it relatively trivial to factor out a given component or system, or construct an object without any rendering in its loop or whatever. Theoretically all systems are independent, but in practice that's obviously not true (the positions and orientations the physics component updates has to be read by the renderer at some point, after all), but it means that code one person touches is generally independent of code someone else touches, and you can test most components and systems in a vacuum devoid of other components. Nothing is stopping you from doing integration testing over multiple components, of course.
That all sounds fantastic actually. Bookmarked for afternoon reading
#12
Old 09-10-2015, 10:21 AM
Guest
Join Date: Sep 2010
Posts: 481
Ok, so as a beginner I just need to wipe the concept of having a table of data that gets referenced and think of objects that have classes/structures assigned to them with the relevant dataholders. And then using Lists and ForEach I can iterate over them.

I guess i was thinking more of loading the initial data as well. So instead of having to say

Player1.Strength = 10;
Player1.Charisma = 10;
Player2.Strength = 20;
...
Player20.Wisdom = 17;

I could just have a spreadsheet that has all players listed that loads to their initial states.

I know there are ways to load datasets from text files and I was extending it to try to load a table. (I know, I need to forget the concept of tables)

Also, I really appreciate the thoughtful answers and you all putting up with my fairly rudimentary questions. I just find a lot of the Unity vids assume that you have a blank slate and can readily absorb the concepts of classes/structures/arrays (arrays kill me because I go straight to thinking of tables... and then dictionaries, hash-tables... all very confusing terminology for a spreadsheet guy) Thanks!!
#13
Old 09-10-2015, 11:17 AM
Member
Join Date: Jun 2000
Location: Los Angeles
Posts: 10,138
Quote:
Originally Posted by Jragon View Post
At AAA, professional, or resource-constrained console or embedded game development levels where the programmers are experienced or resources are extremely scarce, it's probably worth worrying about this. But beginner-level indie game dev in Unity is probably not the best place to explore these bottlenecks. At least not until significant profiling hints it's an issue at least. At the beginner level there's likely much lower hanging fruit than worrying about cache locality or dynamic heap allocations.
Agreed. I'm an old-school C++ programmer, so I tend to keep my data structures lean and simple out of habit. But if he's not resizing the List willy-nilly, it doesn't make much difference.
#14
Old 09-10-2015, 12:17 PM
Guest
Join Date: Aug 1999
Location: Stockholm, Sweden
Posts: 5,645
Quote:
Originally Posted by FasterThanMeerkats View Post
Ok, so as a beginner I just need to wipe the concept of having a table of data that gets referenced and think of objects that have classes/structures assigned to them with the relevant dataholders. And then using Lists and ForEach I can iterate over them.

I guess i was thinking more of loading the initial data as well. So instead of having to say

Player1.Strength = 10;
Player1.Charisma = 10;
Player2.Strength = 20;
...
Player20.Wisdom = 17;

I could just have a spreadsheet that has all players listed that loads to their initial states.

I know there are ways to load datasets from text files and I was extending it to try to load a table. (I know, I need to forget the concept of tables)

Also, I really appreciate the thoughtful answers and you all putting up with my fairly rudimentary questions. I just find a lot of the Unity vids assume that you have a blank slate and can readily absorb the concepts of classes/structures/arrays (arrays kill me because I go straight to thinking of tables... and then dictionaries, hash-tables... all very confusing terminology for a spreadsheet guy) Thanks!!
Off the top of my head ...

Each of those Players would indeed be instances of a player object. The basic way of doing this would be creating a GameObject and having a script assigned to it that holds all that info. That script would be a class definition.

If you're going to have a lot of this, it would be better to define this as a prefab. This prefab would then be instantiated with the Instantiate() method.

If you need to keep a list of all object of a certain type, you should keep a list of references to them and add/remove as and when things are instantiated. This is best stored in a Handler class. Handlers are quite common, the are generally scripts attached to a GameObject that is not visible but it is always present in the scene. It can watch for events, update things etc.

The handler would be a bit like:

Code:
using UnityEngine;
using System.Collections;
public class PlayerHandler : MonoBehaviour {
public List<GameObject> players = new List<GameObject>();
void Start()
{
 players = new List<GameObject>();
}
public void createPlayer()
{
 GameObject player = Instantiate(playerPrefab) as GameObject;
 players.Add(player);
}
}
And then the player, as part of the prefab, a bit like:

Code:
using UnityEngine;
using System.Collections;
public class player : MonoBehaviour {
 public int charisma;
 void Awake()
 {
 charisma = 0; // Or whatever initial value
 }
}
You can then iterate through all the elements in the players list and access the public value of charisma.

Code:
foreach (GameObject player in players) {
 Debug.log("Charisma is " + player.charisma);
}
And then in the class for each player object (instance of the prefab) you can access the values defined in the class without having to specify the object.

I hope that helps. All coding done from memory as I am at work.

Last edited by amanset; 09-10-2015 at 12:18 PM.
#15
Old 09-10-2015, 12:25 PM
Guest
Join Date: Aug 1999
Location: Stockholm, Sweden
Posts: 5,645
Oh and if you want to access the players list from a completely different object, you could store a reference to the Handler in your object when it is instantiated (you should only do this really at startup as searching is intensive) and do something like this.

This is a script that would be attached to another GameObject in your scene. It assumes that the PlayerHandler class is attached to a GameObject called "Scripts".

Code:
using UnityEngine;
using System.Collections;
public class ClassAttachedToOtherObject : MonoBehaviour {
 private PlayerHandler playerHandler;
 void Start () 
 {
 playerHandler = GameObject.FindGameObjectWithTag("Scripts").GetComponent<PlayerHandler>();
 }
 public void logCharisma()
 {
 foreach (GameObject player in playerHandler.players) {
 Debug.log("Charisma is " + player.charisma);
 }
 }
}
I *think*. Try it!

Last edited by amanset; 09-10-2015 at 12:28 PM.
#16
Old 09-10-2015, 12:28 PM
Guest
Join Date: Aug 1999
Location: Stockholm, Sweden
Posts: 5,645
Oh, I forgot. If using List I think you need to add this at the top of the script:

Code:
using System.Collections.Generic;
#17
Old 09-10-2015, 01:14 PM
Guest
Join Date: Feb 2011
Posts: 3,706
Quote:
Originally Posted by The Hamster King View Post
If you just need a simple look-up, I'd use an array of structs:

Code:
public struct Character 
{
public String name; public int strength; public int intelligence; public int wisdom;
} // In the class where you use the data, initialize the array: Character[] characters = new Character[50]; // When you need to access an element, use this syntax: characters[10].strength = 18;
Be careful; while this works with an array of a struct, I don't think it will work if characters is defined as a List<Character>.

Instead, to change characters[10].strength to 18, you have to do something like:

Code:
Character C = characters[10];
C.strength = 18;
character[0] = C;
Note that you can use characters[10].strength to read the value; you just can't use it to change the value.
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump


All times are GMT -5. The time now is 06:03 AM.

Copyright © 2017
Best Topics: stare you down lobster pinch pizza with ketchup portland oregon sucks 5th of whiskey builtin object token nose vacuum fathom distance urine bleach farajaka song alot word tv tropes adblock i hate nature chocolate by 1975 bruce lee lats transposing numbers dyslexia montserrat caballe weight restroom etymology pods alternative circle wire melon green shatner esperanto in home golf judo body grey eyed pizza ketchup white cat wine repairing convertible top dick gay casting aluminum sword how does mindflex duel work adrenochrome fear and loathing why are breasts called boobs how long are cold cuts good killing shrub roots with salt concrete parking pad cost fleas on kittens 2 weeks old dried out nail polish how many miles can a toyota corolla last 43 year old woman side effects of dilated eyes price of custom orthotics black bar over eyes meaning is liquid plumr bad for pipes tastes good like a cigarette should do platelet counts fluctuate cash register and credit card systems you may pass on the right if you are on a one way street with two or more lanes. non-conductive metals what is parcel select ground how to find out if someone has died mustang ranch price list bands with 2 drummers is the carbonaro effect show real or fake popcorn ceiling spray paint who makes fmd watches projector for power point presentation brake fluid vs power steering recharging car battery how long mrs. wiggins and mr. tudball what are hubs on a truck why does cleaning your ears feel good