I have a class "Bullet" which I instantiate using a method CreateBullet(), since there are going to be multiple bullets i decided that I should make bullet an array, though this didn't work out and I've spent an hour on trying to fix it.
What I call in my Initialize method:
Bullet bullet[] = Bullet.CreateBullet[1]();
The Bullet class:
class Bullet
{
public float2 position;
public float angle { get; set; }
public float speed { get; set; }
public static Bullet CreateBullet()
{
Bullet bullet = new Bullet()
{
position = new float2()
};
return bullet;
}
public void Move()
{
}
}
Could you please show me what's wrong with the code? Thank you in advance.
With this, you create an array of 5 bullets:
Bullet[] bullets = new Bullet[5];
And then you need to fill the array by creating a bullet for each array entry:
for (int i = 0; i < bullets.Length; i++)
{
bullets[i] = Bullet.CreateBullet();
}
You can wrap this logic in a function:
public Bullet[] CreateBullets(int amount)
{
Bullet[] bullets = new Bullet[amount];
for (int i = 0; i < bullets.Length; i++)
{
bullets[i] = Bullet.CreateBullet();
}
return bullets;
}
And then you can use a function to initialize the array:
public void Test()
{
Bullet[] bullets = CreateBullets(5);
}
You could do something like this, not quite what you where trying to achieve, but it might inspire you a bit more
Usage
// Create your bullets
var bullets = new List<Bullet>();
// Create a raw/empty bullet with default properties
var newBullet1 = new Bullet();
// Create bullet with some initialized properties
var newBullet2 = new Bullet()
{
Angle = 35,
Position = 0,
Speed = 200
};
bullets.Add(newBullet1);
bullets.Add(newBullet2);
Something extra for fun
// Move all your bullets at once
foreach (var bullet in bullets)
{
bullet.Move();
}
Related
I'm working on Unity3d project where the floor has to unfold gradually. I created a script FloorModule.cs where using coroutine the floor tiles are laying out gradually. Each next module has to unfold right after previous is completed. There for I created Spawner.cs to loop a new FloorModule.cs right after previous one is completed.
I can't seem to get my head around how to use coroutine to synchronize the mainloop (Spawner.cs) with subloop on prefab (FloorModule.cs).
Here is the link to the example
https://1drv.ms/u/s!AkVZpIE6f1GV4M5Ju7G5zPOrQcCe8w?e=QrghRT
P.S.
In given example, as loop goes forward I'm using "Reference.cs" class to change some variable values .
FloorModule.cs
public class FloorModule : MonoBehaviour
{
public float zSpacer = 0f;
public int instPrefabCount;
public Transform spawnPoint;
public int lenght = 15;
public int width = 5;
public GameObject floorTiles;
void Start()
{
spawnPoint = GetComponent<Transform>();
StartCoroutine(FwFloorDelay(spawnPoint));
}
public IEnumerator FwFloorDelay(Transform origin)
{
for (int l = 0; l < lenght; l++)
{
float xAngle = 90;
float yPos = 0;
float zPos = 0 + l;
for (int w = 0; w < width; w++)
{
int xSelection = Random.Range(0, 6);
GameObject xFloor = Instantiate(floorTiles, origin);
TileStatusNames(xFloor, l, w);
// defining positiona and angles
float xPos = w + (zSpacer * w);
xFloor.transform.localEulerAngles = new Vector3(xAngle, 0, 0);
xFloor.transform.localPosition = new Vector3(xPos, yPos, zPos);
yield return new WaitForSeconds(.05f);
}
}
Spawner.cs
public class Spawner : MonoBehaviour
{
public GameObject FloorModPrefab;
public References[] referenceScript;
void Start()
{
StartCoroutine(SpawnModules());
}
IEnumerator SpawnModules()
{
for (int i = 0; i < referenceScript.Length; i++)
{
referenceScript[i].instance =
Instantiate(FloorModPrefab, referenceScript[i].ref_spawnPoint.position, referenceScript[i].ref_spawnPoint.rotation);
referenceScript[i].ref_instFloorModCount = i + 1;
referenceScript[i].Setup();
yield return new WaitForSeconds(5f);
}
}
}
References.cs
[Serializable]
public class References
{
FloorModule prefabObjScript;
public GameObject instance;
public int ref_instFloorModCount;
public Transform ref_spawnPoint;
public int ref_Width = 5;
public int ref_Lenght = 15;
public void Setup()
{
// Get references to the components.
prefabObjScript = instance.GetComponent<FloorModule>();
// Set the player numbers to be consistent across the scripts.
prefabObjScript.instPrefabCount = ref_instFloorModCount;
prefabObjScript.spawnPoint = ref_spawnPoint;
prefabObjScript.width = ref_Width;
prefabObjScript.lenght = ref_Lenght;
}
}
I tried to use coroutines unfortunately in given context I realize it's impossible for me to resolve this task.
You can yield a coroutine from within another coroutine.
Changes to your Code
In References change public GameObject instance; to public FloorModule instance;
In Spawner change public GameObject FloorModPrefab; to public FloorModule FloorModPrefab;
Remove the code from Start of FloorModule.
Modify FwFloorDelay to
public IEnumerator FwFloorDelay(Transform origin = null)
{
if (origin == null)
{
origin = transform;
}
...
}
In SpawnModules, chain the floor delay coroutine
IEnumerator SpawnModules()
{
for (int i = 0; i < referenceScript.Length; i++)
{
...
yield return referenceScript[i].instance.FwFloorDelay();
}
}
Your goal should not be to synchronize separate coroutines, but rather to get the code running sequentially in one coroutine.
For example, you could make References.Setup() asynchronous, and then have it invoke FloorModel.FwFloorDelay directly instead of the FloorModel starting its own separate coroutine.
hi I am new to unity3d development with hololens 2
I want to display employee details in the tile which is interactable
see the sample screenshot below.
AS of now, I created a prefab like a custom component but facing issues in data binding.
I have one empty game object on which dynamically instantiating prefab using c# script
I have prefab of employee tile as below
As you can see I have two fields image (emp image) and text (emp name)
A script which is bound to empty game object
public class CreateEmployeeInfoTiles : MonoBehaviour
{
private TextMeshProUGUI textMesh;
private string _employeeName;
private Employee[] emp;
public GameObject employeeTile;
// Start is called before the first frame update
void Start()
{
Employee empobj = new Employee();
emp = empobj.GenrateEmployees(6).ToArray();
employeeTile = Resources.Load("EmployeeTile") as GameObject;
int j = 10;
for (int i = 0; i < emp.Length; i++)
{
var empTi = Instantiate(employeeTile, new Vector3((i * 10), (j * 20), 115), Quaternion.identity) as GameObject;
empTi.SendMessage("BindData", emp[i]);
j =+ 30;
}
}
// Update is called once per frame
void Update()
{
}
}
Employee class as a DTO
public class Employee
{
public string Name { get; set; }
public string Job { get; set; }
public string imageUrl { get; set;}
public List<Employee> GenrateEmployees(int noOfEmployees)
{
var emp = new List<Employee>();
for (int i = 0; i < noOfEmployees; i++)
{
emp.Add(new Employee() { Name = RandomName(), Job = RandomName(),
imageUrl = "https://url/image/placeimg.jpg"});
}
return emp;
}
}
I want to set employee data to respective game object/UI fields in dynamically generated employee tile prefab.
Thanks in advance.
First it seems very strange to me that GenerateEmployees should be an instanced method. You are creating a new Employee just to then generate more. This should rather be a static method I guess!
[Serializable]
public class Employee
{
public string Name;
public string Job;
public string ImageUrl;
// RandomName will also have to be static
public static List<Employee> GenrateEmployees(int noOfEmployees)
{
// Lists in c# grow dynamically bigger.
// It is more efficient to already set the final size
var emp = new List<Employee>(i);
for (int i = 0; i < noOfEmployees; i++)
{
emp.Add(new Employee()
{
Name = RandomName(),
Job = RandomName(),
imageUrl = "https://url/image/placeimg.jpg"
}
);
}
return emp;
}
}
Then there should simply be a certain component (script) attached to the employee prefab like e.g.
public class EmployeeController : MonoBehaviour
{
// These you reference via the Inspector in the prefab
[SerializeField] private Image image;
[SerializeField] private TextMeshProUGUI nameField;
[SerializeField] private TextMeshProUGUI designationField;
// And finally have a method you can call directly
// Using SendMessage is very inefficient and unsecure
public void BindData(Employee data)
{
nameField.text = data.Name;
designationField.text = data.Job;
// Start downloading the image
StartCoroutine(DownloadImage(data.ImageUrl));
}
private IEnumerator DownloadImage(string url)
{
using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url))
{
yield return www.SendWebRequest();
if (www.isNetworkError || uwr.isHttpError)
{
Debug.Log(www.error);
}
else
{
// Get downloaded texture
var texture = DownloadHandlerTexture.GetContent(www);
// Create a sprite from the texture
var sprite = Sprite.Create(texture, new Rect(0,0, texture.width, texture.height), Vector2.one * 0.5f);
// Assign it to the image
image.sprite = sprite;
}
}
}
}
And finally you would simply use the static method to create Employee data and then use GetComponent to retrieve a reference to the EmployeeController component on the instantiated prefab. Even better would be not using Resources at all! Rather put the prefab in a normal folder and directly drag&drop it into the prefab field of CrrateEmployeeInfoTiles
public class CreateEmployeeInfoTiles : MonoBehaviour
{
// NOTE: Do NOT use Resources!
// rather place your prefab in any other folder and then simply drag it in here
// via the Inspector!
// By using directly the correct type instead of GameObject you
// a) do not need the GetComponent later since Instantiate already returns the dsme type
// b) have more security since now you only can drag&drop a GameObject here
// that actually has the required component attached
[SerializeField] private EmployeeController employeePrefab;
// Start is called before the first frame update
private void Start()
{
var employeeData = Employee.GenrateEmployees(6).ToArray();
var j = 10;
for (int i = 0; i < employeeData.Length; i++)
{
// Since employeePrefab is of type EmployeeController
// Instantiate already returns the component reference
var employee = Instantiate(employeePrefab, new Vector3((i * 10), (j * 20), 115), Quaternion.identity);
employee.BindData(emp[i]);
j =+ 30;
}
}
}
Typed on smartphone but I hope the idea gets clear
I'm trying to call a method CreateFinalPath() using recursion but Unity freezes the second time I call the methode Test().
Do you have any idea what the problem could be?
I nearly tried everything , no clue what is going on.
public class SplinePlus : MonoBehaviour
{
int h = 0;
public void Test()
{
FinalPath.Vertices.Clear();
FinalPath.Tangents.Clear();
FinalPath.Normals.Clear();
CreateFinalPath();
}
private void CreateFinalPath()
{
for (int i = 0; i < Branches[h].Vertices.Count; i++)// branch vertices
{
for (int n = 0; n < SharedNodes.Count; n++) // shared nodes loop
{
if (SharedNodes[n].Nodes.Point.position == Branches[h].Vertices[i]) // shared node detected , see next branch to take
{
h = SharedNodes[n].BranchToFollow; // next branch ID to take
CreateFinalPath(); // trigger data storage for the new branch in Final path class
break;
}
}
// data storage in finalpath class
FinalPath.Vertices.Add(Branches[h].Vertices[i]);
FinalPath.Normals.Add(Branches[h].Normals[i]);
FinalPath.Tangents.Add(Branches[h].Tangents[i]);
}
}
}
public class FinalPath
{
public List<Vector3> Vertices = new List<Vector3>();
public List<Vector3> Tangents = new List<Vector3>();
public List<Vector3> Normals = new List<Vector3>();
}
public class Branches
{
public List<Vector3> Vertices = new List<Vector3>();
public List<Vector3> Tangents = new List<Vector3>();
public List<Vector3> Normals = new List<Vector3>();
public List<PathPoint> PathPoints = new List<PathPoint>();
}
[System.Serializable]
public class SharedNodesData
{
public PathPoint Nodes = new PathPoint();
public List<string> ConnectedBranches = new List<string>();
public int BranchToFollow = 0;
}
Update2
So what I'm trying to do is to create a final path for a gameObject follower based on a complex path system where there is a main branch (red) and the children branches (yellow) which can be in unlimited number.
The shared nodes are the points with numbers on top of them, I'm looping through the main branch first looking for a shared node, once I find one, I can get the next branch index to take which is defined by the user in an the inspector. I affect that to "h" and call CreateFinalPath() to do the same for the next branch until I get the final complete path.
I didt understand much your codes but maybe you need some things like this
public class Branches
{
public List<Vector3> Vertices = new List<Vector3>();
public List<Vector3> Tangents = new List<Vector3>();
public List<Vector3> Normals = new List<Vector3>();
public List<PathPoint> PathPoints = new List<PathPoint>();
public bool visited = false;
}
private void CreateFinalPath()
{
for (int i = 0; i < Branches[h].Vertices.Count; i++)// branch vertices
{
for (int n = 0; n < SharedNodes.Count; n++) // shared nodes loop
{
if (!Branches[h].visited && SharedNodes[n].Nodes.Point.position == Branches[h].Vertices[i]) // shared node detected , see next branch to take
{
Branches[h].visited = true;
h = SharedNodes[n].BranchToFollow; // next branch ID to take
CreateFinalPath(); // trigger data storage for the new branch in Final path class
break;
}
}
// data storage in finalpath class
FinalPath.Vertices.Add(Branches[h].Vertices[i]);
FinalPath.Normals.Add(Branches[h].Normals[i]);
FinalPath.Tangents.Add(Branches[h].Tangents[i]);
}
}
I created a custom class:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Obstacle {
public GameObject gameObj;
public Color color;
public GameObject starExplosion;
public GameObject regular_Trail;
[HideInInspector]
public bool firstCollistion = true;
public static Vector3 SpawnLocation()
{
int positionQuadran = Random.Range(1, 3);
switch (positionQuadran)
{
//spawn above the player
case 1:
return new Vector3(Random.Range(1.5f, -1.5f),
Random.Range(4f - SpawnStars.closerToPlayer, 4.5f),
Random.Range(1, -3.2f));
//spawn benith the player
case 2:
return new Vector3(Random.Range(1.5f, -1.5f),
Random.Range(-0.5f, SpawnStars.closerToPlayer),
Random.Range(1f, -3.2f));
}
return Vector3.zero;
}
}
Now, as you can see in this class there is a variable public GameObject gameObj; Now in another script I need to acces the instance of the Obstacle class that this gameObj instance is in. And I am trying to do that like this:
private void OnCollisionEnter(Collision collision)
{
collision.collider. //what do I do next?
}
For a few reasons I don't want to make the Obstacle class inherit from MonoBehaviour. Since I can't access this class from another GameObject that would be in the scene how do I access it by only knowing the gameObj variable?
Update I will add the script that I use to generate the Obstacle Class:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnStars : MonoBehaviour
{
[SerializeField]
private List<Obstacle> obstacles;
[HideInInspector]
public List<Obstacle> normalStarsPool = new List<Obstacle>();
[SerializeField]
private List<Obstacle> otherObstacles;
[HideInInspector]
public List<Obstacle> otherObstaclesPool;
[SerializeField]
private int spawnNumber = 2;
private Obstacle nextObstacleToSpawn;
[SerializeField]
public GameObject panel;
public static bool spawnNow = true;
public static bool first_find_star = true;
public static float starSpeed;
/* this variables will make the stars to spawn closer and closer to the player as
the score is progresing*/
public static float closerToPlayer;
private float spawnPositionZ;
private void Start()
{
first_find_star = true;
spawnNow = true;
GeneratePrefabs(spawnNumber, obstacles, normalStarsPool);
StartCoroutine(ShuffleList(normalStarsPool));
GeneratePrefabs(2, otherObstacles, otherObstaclesPool);
StartCoroutine(ShuffleList(otherObstaclesPool));
}
private void LateUpdate()
{
if (spawnNow)
{
spawnNow = false;
if (first_find_star)
{
nextObstacleToSpawn = FindStar(normalStarsPool);
first_find_star = false;
}
//spawn the current star
int randomNumber = Random.Range(0, 100);
if(randomNumber >= 20){
nextObstacleToSpawn = FindStar(normalStarsPool);
}
else{
Debug.Log("corrupt star");
nextObstacleToSpawn = FindStar(otherObstacles);
}
SpawnStar(nextObstacleToSpawn);
}
}
void GeneratePrefabs(int how_many, List<Obstacle> prefabList, List<Obstacle> poolList)
{
foreach (Obstacle prefab in prefabList)
{
for (int i = 0; i <= how_many; i++)
{
Obstacle go = new Obstacle
{
gameObj = Instantiate(prefab.gameObj)
};
go.regular_Trail = go.gameObj.transform.GetChild(1).gameObject;
go.starExplosion = go.gameObj.transform.GetChild(0).gameObject;
go.color = prefab.color;
go.gameObj.SetActive(false);
//setap all the colors for the obstacle
ParticleSystem ps = go.starExplosion.GetComponent<ParticleSystem>();
ParticleSystem.MainModule psmain = ps.main;
psmain.startColor = go.color;
//setup the collor of a partycle system
ps = go.starExplosion.GetComponent<ParticleSystem>();
psmain = ps.main;
psmain.startColor = go.color;
psmain.startColor = go.color;
go.gameObj.GetComponent<Renderer>().material.color = go.color;
poolList.Add(go);
}
}
}
Obstacle FindStar(List<Obstacle> poolList)
{
while (true)
{
int randomIndex = Random.Range(0, poolList.Count);
if (!poolList[randomIndex].gameObj.activeInHierarchy)
{
Color color = poolList[randomIndex].color;
color.a = 0.5f;
panel.GetComponent<Renderer>().material.color = color;
return poolList[randomIndex];
}
else randomIndex = Random.Range(0, poolList.Count);
}
}
void SpawnStar(Obstacle star)
{
star.firstCollistion = false;
star.starExplosion.SetActive(false);
star.regular_Trail.SetActive(true);
star.gameObj.GetComponent<MeshRenderer>().enabled = true;
ScaleDifficulty();
star.gameObj.transform.position = Obstacle.SpawnLocation();
star.gameObj.SetActive(true);
}
//Shuffle a list every 4 seconds, don't pus this in an update or something cuz it's a coroutine
IEnumerator ShuffleList(List<Obstacle> list_to_Shuffle)
{
while (true)
{
yield return new WaitForSeconds(4f);
for (int i = 0; i < list_to_Shuffle.Count; i++)
{
Obstacle temp = list_to_Shuffle[i];
int randomIndex = Random.Range(i, list_to_Shuffle.Count);
list_to_Shuffle[i] = list_to_Shuffle[randomIndex];
list_to_Shuffle[randomIndex] = temp;
}
}
}
//this will scale the difficulty as the score get's higher and higher
public void ScaleDifficulty()
{
if (Menu.score < 60)
{
//the speed of the star as the score goes up
starSpeed = ((float)Menu.score / 30) + 1f;
//how close relative to the player will the stars spawn in the x and y axis?
closerToPlayer += Menu.score / 60;
// Debug.Log(starSpeed);
}
}
}
As you can see i generated the Obstacle objects in this method:
void GeneratePrefabs(int how_many, List<Obstacle> prefabList, List<Obstacle> poolList)
{
foreach (Obstacle prefab in prefabList)
{
for (int i = 0; i <= how_many; i++)
{
Obstacle go = new Obstacle
{
gameObj = Instantiate(prefab.gameObj)
};
go.regular_Trail = go.gameObj.transform.GetChild(1).gameObject;
go.starExplosion = go.gameObj.transform.GetChild(0).gameObject;
go.color = prefab.color;
go.gameObj.SetActive(false);
//setap all the colors for the obstacle
ParticleSystem ps = go.starExplosion.GetComponent<ParticleSystem>();
ParticleSystem.MainModule psmain = ps.main;
psmain.startColor = go.color;
//setup the collor of a partycle system
ps = go.starExplosion.GetComponent<ParticleSystem>();
psmain = ps.main;
psmain.startColor = go.color;
psmain.startColor = go.color;
go.gameObj.GetComponent<Renderer>().material.color = go.color;
poolList.Add(go);
}
}
}
In short, you can't. Not the way you've got things set up. If you need to access that object globally, you'll need to keep track of it globally. Unity provides a way to do that (essentially the Service Locator pattern), but you've said you don't want to use it. So you're going to have to build your own.
Assuming you've got a collection of your Obstacle objects, e.g. IList<Obstacle> obstacles you could get it by obstacles.Where(o => o.gameObj == myLocalGameObjReference). A better solution, assuming you have this script attached 1:1 for each Obstacle would be to simple inject the Obstacle into the script. Look at a dependency injection (DI) framework like Zenject to assist with configuring and managing your dependencies. Another alternative is the singleton pattern. Personally, I'd opt for DI over singleton. The singleton seems easier at first, but you'll quickly run into trouble with it.
Now in another script I need to acces the instance of the Obstacle class that this gameObj instance is in.
Given an instance of an Obstacle class, how can you even know that it is referenced by an instance of GameObject at all? Or how can you know that it's referenced by only one GameObject?
Unless there's a two-way reference - the GameObject has a reference to the Obstacle and the Obstacle also has a reference back to the GameObject - there's no way to determine what references an instance of Obstacle.
I was working on a simple turn based RPG game. I was working on a battle system. I had it working with 1 enemy, and wanted to update it to work on multiple enemies. I have it spawning multiple enemies, but I am having issues targeting them.
Basically, the enemies are stored in a list called actualEnemies. The enemies are generated at run time, and there can be between 1-3. A label is generated to display the enemy name, and the enemy is selected by double clicking on it.
The issue seems to be in the naming of the enemy's. They have a property called characterName to identify an enemy. The problem is, there can be 2 or more of the same type of character (for example, 3x Goblin). So in the code where the enemies are generated, I was wanting to add a 1 to the characterName if there already is one in the list. The idea is to give each enemy a unique name.
The problem is, when I try this, it changes the values of all of the enemies of the same name, and this is screwing with everything. Here is the relevant section of code:
if (EnemyExists(e)) {
e.characterName += c.ToString();
}
c is simply a counter that is being used, to let me know if it is enemy 1, 2 or 3.
The EnemyExists function is as follows:
public bool EnemyExists(Enemy e) {
bool exists = false;
int eCount = 0;
foreach (Enemy en in actualEnemies) {
if (en.characterName == e.characterName) {
eCount++;
}
}
if (eCount > 1) {
exists = true;
}
return exists;
}
Just to note, the enemies all start off with a default name. For this example I am working on, there are only 2 kinds of enemy. The game picks a random number between 1-3, to decide how many enemies there are. Each enemy will be one of the 2 pre defined enemies, picked at random again. This is why I just want to add a number to the end of a name that is already present.
I suspect it has something to do with how I am creating the list of enemies:
public void CreateActualEnemies() {
int r;
int potEnemyNum = potentialEnemies.Count;
int numEnemies;
Random rand = new Random();
numEnemies = rand.Next(1, 4 );
for (int i = 0; i < numEnemies; i++) {
r = rand.Next(0,potEnemyNum);
Enemy ene = new Enemy();
ene = potentialEnemies.ElementAt(r);
actualEnemies.Add(ene);
}
DisplayEnemyDetails();
}
When I add to actualEnemies, am I just pointing to an address in potentialEnemies, so even though I am instantiating a new Enemy, each one, if it has the same name, points to the same place? Do I need to properly copy the object?
It is late, I am tired, but I feel like I am getting closer, any help would be great, thanks.
EDIT:
Enemy Class:
public class Enemy:Character {
public int xpGiven { get; set; }
public LootTable lootTable { get; set; }
public int goldDropped { get; set; }
public bool alive { get; set; }
public NamedTimer timer { get; set; }
public Enemy() {
alive = true;
xpGiven = 10;
lootTable = new LootTable();
goldDropped = 10;
timer = new NamedTimer();
}
}
Breaking down your question:
When I add to actualEnemies, am I just pointing to an address in potentialEnemies, so even though I am instantiating a new Enemy, each one, if it has the same name, points to the same place?
By doing
Enemy ene = new Enemy();
You are essentialy creating a new pointer in memory with a "blank" valued-reference.
However, since you did
ene = potentialEnemies.ElementAt(r);
You overwrote it with the reference to the element in the list. So whatever changes you do the ene object will reflect the item in the list.
If you want to segregate said changes, try using a MemberwiseClone.
From the example given at MSDN:
public class Person
{
public int Age;
public string Name;
public IdInfo IdInfo;
public Person ShallowCopy()
{
return (Person) this.MemberwiseClone();
}
public Person DeepCopy()
{
Person other = (Person) this.MemberwiseClone();
other.IdInfo = new IdInfo(IdInfo.IdNumber);
other.Name = String.Copy(Name);
return other;
}
}
1: Property names should start with a capital letter in C#. I.e. public int xpGiven { get; set; } should be public int XpGiven { get; set; }. If it's a class variable (no get or set defined), you start with a lower case letter. To more easily identify class variables from local variables, programmers typically start them with a _, although this is not mandatory.
2: When doing ==, please be aware enemyA == enemya will return false. Use enemyA.Equals(enemya, StringComparison.OrdinalIgnoreCase) to ignore capital differences.
3:
public void CreateActualEnemies()
{
int r;
int potEnemyNum = potentialEnemies.Count;
int numEnemies;
Random rand = new Random();
numEnemies = rand.Next(1, 4 );
for (int i = 0; i < numEnemies; i++)
{
r = rand.Next(0,potEnemyNum);
Enemy ene = new Enemy();
ene = potentialEnemies.ElementAt(r);
actualEnemies.Add(ene);
}
DisplayEnemyDetails();
}
should be:
public void CreateActualEnemies()
{
Random rand = new Random();
int numEnemies = rand.Next(1, 4 );
for (int i = 0; i < numEnemies; i++)
{
Enemy ene = new Enemy();
ene.characterName = "" + ene.GetType().Name + " " + i; // or something similar to give the ene a unique name.
actualEnemies.Add(ene);
}
DisplayEnemyDetails();
}