Skip to main content
GameDev.net gamedev.net
🔒 Locked 🎮 Unity

How to program smarter??

Started by ggenije Nov 30, 2018 at 7:26 PM 19 replies 3.5k views
Original Post
ggenije
ggenije

My question:

For example I have class enemy, let's say I have 100 enemy types.

Now in Update()(each frame)


if(enemyType==Type1)
{doWhat Type1 does}
else if(enemyType==Type2)
{doWhat Type2 does}
else if(enemyType==Type3)
{doWhat Type3 does}
...
else if(enemyType==Type100)
{doWhat Type100 does}

so in each frame I can call up to 100*enemy count

so is there any way to avoid this , to tell it earlier what update should it do

I am working in unity, but is there universal way or?


EeksGames
EeksGames

What you're talking about is efficiency. To get better you have to find all the long code segments that can become smaller segments. It takes time, but the key is knowing the language. The more you know about the language the more efficient you will become. In game dev if you are starting as a coder, the last place you might want to start is with a game. If you're using C# study C#. Learn about classes and objects, you really need them. Learning web development opened my eyes too. Learning data bases with mysql carries over nicely to sqlite (embedded data base for software.) Learning the web stuff opened my eyes on how to update software via downloads (Unity asset bundles.)

To get rid of your jumble of if statements you want to make prefabs of your bad guys. Make a bad guy, attach scripts to it, and make that a prefab. Then you are controlling one bad guy at a time. And you want to do prefabs of all your bad guy types. It's like programming behaviors. When you drop the prefab in the scene they will all behave according to the attached code. I'm kind of a newbie too, so research prefabs. That will get the ball rolling a bit. And remember what I said about learning the language in general, and taking a peek at web programming. Game dev is a long haul. For someone like me, I had to settle for text game for now, because a graphical game will not happen without funding, and a couple of smart coders.

ggenije
ggenije
17 minutes ago, EeksGames said:

What you're talking about is efficiency. To get better you have to find all the long code segments that can become smaller segments. It takes time, but the key is knowing the language. The more you know about the language the more efficient you will become. In game dev if you are starting as a coder, the last place you might want to start is with a game. If you're using C# study C#. Learn about classes and objects, you really need them. Learning web development opened my eyes too. Learning data bases with mysql carries over nicely to sqlite (embedded data base for software.) Learning the web stuff opened my eyes on how to update software via downloads (Unity asset bundles.)

To get rid of your jumble of if statements you want to make prefabs of your bad guys. Make a bad guy, attach scripts to it, and make that a prefab. Then you are controlling one bad guy at a time. And you want to do prefabs of all your bad guy types. It's like programming behaviors. When you drop the prefab in the scene they will all behave according to the attached code. I'm kind of a newbie too, so research prefabs. That will get the ball rolling a bit. And remember what I said about learning the language in general, and taking a peek at web programming. Game dev is a long haul. For someone like me, I had to settle for text game for now, because a graphical game will not happen without funding, and a couple of smart coders.

My problem isn't that I have many if statements,but to do it only once, not in every update.

JoeJ
JoeJ
33 minutes ago, ggenije said:

so is there any way to avoid this , to tell it earlier what update should it do

The first thing to try is probably to make behavior data driven, not code driven.

So all the ifs process similar code with some branches, but what happens exactly is driven by data that can be tweaked by a game designer (non programmer) with editing a text file, for instance containing the number of damage a certain type of enemy does.

As a bonus chances increase you can reuse the code in a later game where only the data needs to be adapted.

EeksGames
EeksGames

If you really want to just do it once you need to wrap it in another if statement with a flag bool. Maybe someone can suggest something better.


if(doingtask)
{

  // process here

}

You need to find a constructive way to trip taskdone on and off, while watching out for making it flicker on and off in your update.

You could also have an array of string flags.


Alberth
Alberth

Wouldn't a switch over the enemy type work? At least it beats sequentially testing so many values. The compiler will likely convert it to a dispatch table, so it jumps directly to the right piece of code.

EeksGames
EeksGames

Also supply samples of your actual code, so people can see exactly what you're doing. I think you'll get better tailored support with code and an explanation. It's hard for people if they have no clue what you're trying to do.

Gnollrunner
Gnollrunner

In your specific example it should take one check rather than 100. There are a number of ways to handle this situation given the language you are using and your preference. I program in C++ so this will be the basis for my answer

Imagine each enemy type can be considered a number: 1 to 100. Now it's simple enough to set up a table of function (pointers) for your different behaviors. You index the table by your enemy type, call the behavior, and you are done. In C++ and similar languages you can also set up 100 little subclasses that all over ride a virtual for specific behaviors. Likewise this will more or less give you a single dispatch, so the performance will be good, and it should work in C# also. Probably the table dispatch will also work.


ggenije
ggenije

What I am doing is next:

with class Enemy there is type Boss and non Boss(minions) i use same model for minions and bosses , just scaled.

99.99% of enemies are minions and they behave the same (expect some minor things that happens once in few seconds)

but 0,001% are boss that behave differently.

So why call a millions of unnecessary if statements?

I know that this statements they do not bother too much , but what is there a lot of different types/behaviors .

Also different bosses doing different things.


Gnollrunner
Gnollrunner
20 minutes ago, ggenije said:

What I am doing is next:

with class Enemy there is type Boss and non Boss(minions) i use same model for minions and bosses , just scaled.

99.99% of enemies are minions and they behave the same (expect some minor things that happens once in few seconds)

but 0,001% are boss that behave differently.

So why call a millions of unnecessary if statements?

I know that this statements they do not bother too much , but what is there a lot of different types/behaviors .

Also different bosses doing different things.


I can't decern what your exact requirements are, however IMO much of what you are trying to do can be handled with basic polymorphism (virtual functions and overrides) like I aluded to at the end of my first reply. You should be able to dump the vast majority of your ifs.

JoeJ
JoeJ
59 minutes ago, ggenije said:

So why call a millions of unnecessary if statements?

If you want to avoid this completely the only way is to have one array for small minions and a second for large minions. So you have two Update functions too, each looping only over the appropriate enemy type and no others.

ggenije
ggenije

Like this?


public class Enemy
{
    float health;
	float attack;
	float speed;
	void Attack(){}...
}
public class Minion : MonoBehaviour
{
  Enemy enemy;
    void Update()
    {
		MinionWork...
    }
}
public class Boss : MonoBehaviour
{
  	Enemy enemy;
    void Update()
    {
		BossWork...
    }
}


Gnollrunner
Gnollrunner
16 minutes ago, ggenije said:

Like this?



public class Enemy
{
    float health;
	float attack;
	float speed;
	void Attack(){}...
}
public class Minion : MonoBehaviour
{
  Enemy enemy;
    void Update()
    {
		MinionWork...
    }
}
public class Boss : MonoBehaviour
{
  	Enemy enemy;
    void Update()
    {
		BossWork...
    }
}


Again It's been a while for me with C# but assuming MonoBehavior is either a class with a virtual Update, or an interface, something like that could work. Then you can just keep an array of MonoBehavior objects and call Update on them all. You can also subclass for specific kinds of Minion and Bosses if you need to.

JoeJ
JoeJ
26 minutes ago, ggenije said:

Like this?

Yes.

But eventually since now both classes have an Enemy, there might be a more elegant way to handle this using the ECS system Unity is built upon. But i have no experience here... anyone?

What seems wrong to me is the Attack function now being unaware if being a boss or a minion.

There likely is a better way, probably obvious to people more familiar with Unity, ECS and gameplay code than me...



Gnollrunner
Gnollrunner

He can easily move Attack and/or other functions to MonoBehavior and rename it to MultiBehavior, or alternatively create more interfaces. There are a lot of options.

Septopus
Septopus
46 minutes ago, Gnollrunner said:

I was more speaking in terms of general program options. Any C#/Unity specific stuff I'll defer to you on.

Haha, don't defer anything to me!

I only found that link while trying to understand and put into context, what you were saying. ;)

Gnollrunner
Gnollrunner
28 minutes ago, Septopus said:

Haha, don't defer anything to me!

I only found that link while trying to understand and put into context, what you were saying. ;)

Still...You program in C# Unity every day. I program in C++ DX11 everyday, haven't programed in C# in years, and never used Unity. I'm sure you know some things I don't.?


EeksGames
EeksGames

If you want in-depth help with this situation you might need to supply some screen shots of the editor, what your attachments are to game objects, and some sample code (as mentioned).

You said you want your minions to all act the same. What you have to do is have to do is create the game object, attach scripts, and create a prefab. Then they will all act according to the code attached. Can I ask something? What is the minor different thing the minions do? Do they all do this minor different thing at a random time, or just some of them do it? If just some of them do it, you could create two prefabs of the same enemy. One with that behavior and one without. If you want that code on all of them you're going to have to make a class variable to determine if they are doing it.

Minion - will walk about randomly, tap his foot on the ground if no one is in ear shot, have a seat.

If you want to say a minion doesn't do one of those things you could have class member that is an array of behaviors.

array behaviors['walk about', 'tap foot impatiently', 'have a seat on ground'];

When you instantiate the objects you could just leave one out. And your inner code would look in the array for behaviors and see if the condition is right.

EDIT: Sorry, I didn't see the end 6 posts. I didn't know you had elaborated.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.