Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
25
Question by e-bonneville · Apr 22, 2010 at 02:04 AM · variablesscriptingbasicsbestpractices

What are some good scripting habits?

What are some good scripting habits to form? For example, is it a good idea to expose variables in your code, such as the speed of your car or the damage done by an attack? What are some more good ideas to keep in mind while writing script? Is it a good idea make lots of files or to have most of your script in a few well-written files?

Comment
Add comment · Show 7
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image qJake · Apr 22, 2010 at 02:22 AM 3
Share

This is the type of question that could benefit from a community wiki posting.

avatar image e-bonneville · Apr 22, 2010 at 02:28 AM 0
Share

Hmm... Yeah, I'll think about it. I do need rep, you know. I'm this close [snap of fingers] to a grand. Perhaps an wiki answer would be useful in this case?

avatar image Cyclops · Apr 22, 2010 at 09:56 PM 0
Share

I really think you should make the Question more Unity-specific. Although the Answers given are good (and I would never vote down the mighty @Duck :) , still, he's describing indentation standards - which are really general-program$$anonymous$$g best practices. And there are hundreds of principles, sites, books, etc on good program$$anonymous$$g practices. If we start listing them all here, this Question could go for hundreds of pages. :)

avatar image e-bonneville · Apr 22, 2010 at 10:52 PM 0
Share

Yeah, but why not? I mean, that's hundreds of pages of help... although, actually, I see what you mean. Ah man... it's good though. Plus, the real, much more sinister purpose of this question was to generate rep and it's currently doing a good job.

avatar image Cyclops · Apr 22, 2010 at 11:30 PM 0
Share

@elbon96 - can't argue with that... :)

Show more comments

3 Replies

· Add your reply
  • Sort: 
avatar image
38
Best Answer

Answer by duck · Apr 22, 2010 at 09:25 AM

Here's a good basic one that crops up a lot for beginner programmers:

Try to achieve a good "separation of concerns"

Try to separate and organise the various responsibilities and actions so that - as much as possible - the various entities within your game don't have to concern themselves with the inner workings of any other entity.

For example - a fairly typical player/enemy interaction - when a particular kind of roaming enemy touches your player object, you might think along these lines:

  • The enemy should deduct health from the player.

  • A "damage" sound should be played,

  • The player should become invincible for 5 seconds (or...)

  • The player should be destroyed if their health reaches zero

A beginner might start scripting it like this:

// -- enemy script -- var player : Player;

function OnCollisionEnter(c : Collision) { if (c.transform == player) { player.health -= 5; if (player.health < 0) { Destroy(player); } } }

Which is fair enough, and will probably work. However there are problems here:

  • What if there are other types of enemy, or other things which aren't even enemies - like lava, spikes, etc - which should also be able to damage the player? Should they all have their own code which checks the health of the player and destroys it?

  • What about invincibility, are they each going to have to perform their own checks as to whether the player is invincible?

  • Where should we put the code for generating the players "damage" sound effect?

  • What about a graphical health bar? if many objects can independently update this "health" variable, there's no central point which we can tap into as a "notification" that the health value has changed.

All these issues can be resolved by separating each object's concerns - the enemy should not have to be aware of any of the process involved after simply "attacking" the player.

In fact, if you generalise it right out, your enemies ought to be able to simply "attack" anything that is marked as attackable, and let the thing which was attacked deal with the consequences!

You can implement this by moving the code which deals with the consequences of the attack onto the object which was attacked - i.e. the player. For example, your enemy script would now look like this - simply calling an "TakeDamage" function on the player:

// -- enemy script --
function OnCollisionEnter(c : Collision) {
    if (c.gameObject == player) {
        player.TakeDamage(5);
    }
}    

Your player would then respond accordingly in its own function:

// -- player script -- var healthBar : HealthBar; private var health = 10; private var invincibleTime = 0;

function TakeDamage(amount : int) {

 if (Time.time &lt; invincibleTime) {
     // ha! I am invincible!
 } else {
     // reduce health
     health -= amount;

     // update health bar
     healthBar.Show(health);

     if (health &lt;= 0) {
         // gah! we died!
         audio.clip = dieSound;
         audio.Play();
         Destroy(gameObject);
     } else {
         // make invincible!
         invincibleTime = Time.time + 5;
     }
 }

}

Hopefully this illustrates how you could now have various other types of hazards - both enemies and scenery, and all any of them need to do is call the player's "ApplyDamage" function when appropriate.

The techniques described here fall roughly into the formal programming principles of "Separation of Concerns", and "Encapsulation (a.k.a. Information Hiding)", and can be applied throughout your whole game, not just between player and enemy interactions.

Something that is relevant, but not described here, are the principles of Inheritance and Interfaces, which - in the context of the example in this question - would give you a formal way of defining that an object or that a certain class of objects are "attackable", and are guaranteed to have an "ApplyDamage" function.

In real-life programming there are often ambiguities, where it appears as though perhaps two or more objects share a concern. In this case, there may be no "right" answer, but as long as you are bearing these ideas in mind, your game systems should benefit!

Comment
Add comment · Show 7 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image e-bonneville · Apr 22, 2010 at 11:56 AM 0
Share

@Duck Wow, nice answer. Well, I've certainly gained some knowledge here. Thanks a lot!

avatar image Clave · Apr 22, 2010 at 12:12 PM 0
Share

i've been looking for sumthing like this long time ago. thank you! :D

avatar image Clave · Apr 24, 2010 at 04:14 AM 0
Share

in the 'enemy' script, do i have to include a line like this playerScript : playerScript. so i can access the player.TakeDamage(5) function?

avatar image duck ♦♦ · Apr 24, 2010 at 08:18 AM 0
Share

yes, although it should be: var player : Player, assu$$anonymous$$g your script is named "Player". (No need to add the word script!).

avatar image Clave · Apr 24, 2010 at 04:57 PM 0
Share

thank you! uhmm. . one more thing! let's say the enemy script has a DoDamage() function, and in the game scene, there are 50 instances of enemy, so its gonna be like there are 50 copies of enemy script. therefor, 50 DoDamage functions. can't we like separate and put the DoDamage function to a different script, so all 50 enemy instance will only refer to a single script when using the DoDamage function. or is it the same thing having their own DoDamage function? is there any memory consumption difference?

Show more comments
avatar image
21

Answer by duck · Apr 22, 2010 at 04:56 PM

Here's another scripting habit I recommend:

Choose a coding style and stick to it.

There have been ongoing coding "style wars" for decades. The most important thing is that you choose a consistent readable style, and if you're working with others, make sure your style is consistent with theirs. Often, established software companies will have their own "house style" which usually closely matches industry standard style guidelines for their particular language

These are some of the basic styles I stick to:


Use proper indentation and add whitespace for readability.

Many decent code editors will auto-indent as you type, and offer a retro-active autoformat tool too. I don't care if the braces come on the same line, or on the next line, as long as the indentation is correct! Use brackets even if your 'if' or loop has only one statement inside. Read about Indent Styles on Wikipedia.

Bad:

function FeedAnimals () {
for (var animal in Animals) {
if (animal.diet == Diet.Carnivore)
{
animal.Feed(new Meat());}
else
{
animal.Feed(new Fruit()); }
}
}

Good:

function FeedAnimals () {

 for (var animal in Animals) {

     if (animal.diet == Diet.Carnivore) {
         animal.Feed(new Meat());
     } else {
         animal.Feed(new Fruit());
     }

 }

}


use comments, but use them sparingly

Write your code as if comments didn't exist, and only then add comments if extra clarity is required, eg, to give a "title" to a block of code, or to explain something particularly unusual or obscure.

For example:

// feed each animal its appropriate food
for (var animal in Animals) {
    if (animal.diet == Diet.Carnivore) {
        animal.Feed(new Meat());
    } else {
        animal.Feed(new Fruit());
    }
}

I don't think any other comments are necessary in this block. The names chosen for the variables, and functions lead to comprehensible code. Which leads me to my next point...


Name your classes, functions and variables sensibly

These are all guidelines, and there will be exceptions, but try to bear these in mind. Use PascalCase and camelCase appropriately.

Function/Method names should usually:

  • use PascalCase
  • be verbs, or verb phrases (eg "Fire()", "ApplyDamage()", "CollectPowerup()")

Class names should usually:

  • use PascalCase
  • be nouns or noun phrases (eg, "Enemy", "Bullet", "Player" )
  • not have redundant suffixes like "Control", "Script", or "Object"
  • be singular, even if you're going to instantiate lots of them!

Variable names should usually:

  • use camelCase
  • be nouns (but with exceptions, eg booleans often need verb phrases)
  • be plural if the value is an array/collection (eg, enemies, bullets, people)
  • not contain information about the type of data (unless it's an index/counter)
  • not contain abbreviations (unless generally well understood like MPH, Max)

Bad:

function bullets() {... // (...not a verb or verb phrase, and not PascalCase)

var spcRmn;
// (...you don't need to abbreviate!)

for (var i=0; i<j; i++) {...
// (...you should describe what you're counting! // except for the most 'trivial' of loops)

var powerupArray : Powerup[]; // (...you don't need to use "array" in the name!)

class Robots extends Enemy {... // (...don't use plural, think of each instance - it's a "Robot")

Good:

function FireBullet() { // (...describes what the function does)

var spaceRemaining; // (...no need for abbreviations)

for (var sheepNum=0; sheepNum < sheep.Length; sheepNum++) { // (...ah, we're counting sheep! and sheepNum is the current index)

var powerups : Powerup[]; // (...instead of using the word "array", just pluralise it)

class Robot extends Enemy { ... // (...classes should almost always be a singular noun)

There are many other areas of programming to which particular styles can be applied and argued over, and this answer should be considered a very basic introduction to the idea. For more information see "Programming Style" on Wikipedia and you might also be interested to read some of the more detailed C# programming style guides out there.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image e-bonneville · Apr 22, 2010 at 08:33 PM 0
Share

@Duck That's great. I'll keep both ideas in $$anonymous$$d. Thanks for the help @Duck.

avatar image
9

Answer by e-bonneville · Apr 22, 2010 at 02:08 AM

Well, for starters, changing variables directly in your code will cause it to recompile after you save, so it's generally a good habit to expose all the variables that you are likely to change a lot, just because it saves time. However, if you're simply getting a reference to a gameobject at runtime, you should make that kind of variable private. Nearly much all variables changed or created at runtime should be kept private. Of course, that depends on what you're trying to do.


The pros and cons of if statements in collisions:

Here are two scripts, kindly provided by unknown(google) to debate the pros and cons of sending messages to every gameobject touched:

The first script uses if statements to detect what it collided with and send messages accordingly:

function OnCollisionEnter(c : Collision) { 
    if (c.gameObject == player) { 
        player.TakeDamage(5); 
    } 
} 

This second script doesn't use if statements. It merely sends damage to all collisions:

function OnCollisionEnter(c : Collision) {
    SendMessage("TakeDamage", c.gameObject, damageAmount); 
}

The first script checks if the gameobject collided with the player. The second damages all gameobjects that are collided with. There several are reasons why the first script is more desirable. First of all, the second script calls a damage message on everything it touches. This may not be a good idea, because if the enemy is walking towards you, it'll constantly be sending messages to the floor about damage. The first script checks if the collider is a player, so if the enemy is walking around, it won't be sending damage messages to the floor, which, with multiple enemies, will end up taking up extra memory.

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jc_lvngstn · Apr 22, 2010 at 12:58 PM 0
Share

Another thing that might be useful is talking about the pros and cons of doing this: // -- enemy script -- function OnCollisionEnter(c : Collision) { if (c.gameObject == player) { player.TakeDamage(5); } }

vs this:

function OnCollisionEnter(c : Collision) { // apologies if the syntax is wrong, I'm at work. Send$$anonymous$$esssage("TakeDamage", c.gameObject, damageAmount); }

avatar image jc_lvngstn · Apr 22, 2010 at 01:08 PM 0
Share

Sorry...let me try again. $$anonymous$$ight be useful to discuss the pros and cons of doing this:

if (c.gameObject == player) { player.TakeDamage(5); }

vs this (syntax maybe off):

Send$$anonymous$$essage("TakeDamage", c.gameObject, damageAmount);

avatar image e-bonneville · Apr 22, 2010 at 01:20 PM 0
Share

I've updated my answer above for you.

avatar image e-bonneville · Apr 22, 2010 at 01:58 PM 0
Share

@Everyone If you have an idea, post it, either as a comment or an answer. We need a single point of reference for this kind of thing.

avatar image Cyclops · Apr 22, 2010 at 09:39 PM 1
Share

$$anonymous$$ight want to take an s out of Send$$anonymous$$esssage. :)

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

No one has followed this question yet.

Related Questions

Is it better to change a similar object's script between scenes for different functionality, or have the script provide different behavior between scenes? 0 Answers

How to access a non static variable by another static variable? 1 Answer

variables within variables? 2 Answers

Reference string from another gameobject and not directly from the script itself? 1 Answer

What is this Mode Selection in Editor and how does it work? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges