Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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
5
Question by runonthespot · Oct 13, 2010 at 08:45 PM · objectscommunicationmessagebestpracticesstructure

Best practice for object communication

Hi there,

I've worked out how to use Find and FindWithTag and GetChildren, but I keep feeling like I'm missing something.

I have a number of objects that for one reason or another are easier to group under a gameObject, e.g. a Spaceship, consisting of a mesh, some particle systems.

I'm finding the process of getting to methods on children (e.g. setting the engine particle emitter off), quite onerous and seldom reusable.

My question is (and this is difficult to frame without sounding too general), what is the best way of structuring objects in a scene and accessing scripts at different levels of children?

Is there some sort of event system, or some sensible way of enumerating objects for later communications?

Thanks, Mike

Comment
Add comment · Show 1
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 Jessy · Oct 13, 2010 at 10:56 PM 0
Share

As I said in my comment for the question below, events are awesome and definitely my recommended approach. However, I'd like to see an example of what you have now, so I can recommend an actual improvement ins$$anonymous$$d of typing up something really abstract that you might not be able to wrap your head around.

3 Replies

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

Answer by duck · Oct 13, 2010 at 10:01 PM

(this answer is largely taken from where I posted the same text as an answer to another question, but it wasn't accepted and so probably doesn't get seen much!)

As you have said in your question, there are a number of functions you can use at runtime to find other objects, but these - as you've suggested - are slightly tedious and don't result in easily reusable code.

The main ways to access other objects and other components are listed on these two manual pages:

Accessing Other Objects

Accessing Other Components

However, there is one method listed within those pages that is quite unique to Unity and very useful, but it is not described in great detail. As a result, many beginners don't spot this feature, so I'm going to write it up in more detail here.

Interestingly - on the flip side - many newcomers to Unity who have experience in other programming environments (which don't have this feature) feel the urge to rebel against it and go for an "All-Code" approach. I'm talking about:

Drag-and-drop Editor References

This is the way that you can create references to scripts on other game objects by literally dragging and dropping GameObjects in the editor. I'm not sure if there's a specific technical term coined for these, but I'm going to call them 'dragged references' from here on.

I'm not suggesting that drag-references are the best option in all situations, I'm mainly stating here that it's good practice to know about this and understand it, and use it where appropriate.

In practice - for any project of significant complexity - you will almost always need a combination of approaches, incuding dragged references, "object managers" which instantiate and track references to dynamically created objects (such as bullets, enemies), direct function calls between objects and event systems.

For instance - even though you could - you probably don't want to creat every instance of each ship in the scene in formations for the levels. Instead - if you have, say, 20 different kinds of ship in the entire game, each defined as a prefab, it might be an idea to have a sort of "Ship Library Manager" class, which itself has a drag-reference just to each ship prefab. This "ship manager" can then instantiate them in whatever formations you like, which can be defined programatically. Because it's creating the ships, it has access to each of their instances which it can store in an array for easy direct messaging.

That said, here is how you go about creating dragged-references. They are created by a simple two-step process:

Step 1: Create a variable in your script, whose type is the exact name of the type of script you want a reference to. For example: a simple "bat and ball" game. You have a player GameObject, which has a "Player" script attached, and a ball GameObject with a "Ball" script attached. In your "Player" script, you would have:

// in Javascript: var ball : Ball;

// or in C# public Ball ball;

This creates a public variable which can contain a reference to an instance of your "Ball" script. (In this example, the variable name is "ball" - a lower-case version of the script's name. This is a common convention, but you could pick any suitable name you like).

Because the variable is public, and your "Ball" script is effectively a Component (because it inherits from MonoBehaviour), the Unity Editor spots this, and makes the variable visible as a special "slot" which is visible in the inspector. You would need to click on your Player GameObject in the hierarchy to see this.

Step 2: Make sure the target variable slot is visible in the inspector, then click and drag the object which has the desired script to be referenced, from the hierarchy pane into the variable slot. This now makes an automatic reference which you can use at runtime to refer to the instance of that script. For the Player and Ball example, you'd click the "Player" object, so that you can see "Ball" variable slot. Then you'd drag the "Ball" GameObject from the hierarchy pane straight into that variable slot.

That's it.

You can also have a script which has variables that can contain references to other instances of the script itself. For example "ScriptA" might have a public variable which is also of type "ScriptA". A practical example of why you might want this could possibly be a tennis game, where you might have variables set up in the "Player" script like this:

// script is called "Player.js"

var ball : Ball; var otherPlayer : Player;

In this example, we have one public variable ready to have the 'ball' object dragged into it. However we also have a variable called "otherPlayer", whose type is "Player" (the name of the script itself). This is so that you could have two players, and each player would be set up with a dragged-in reference to the other player - their opponent.

You can also have arrays of dragged references. For example, in a game where there are ten targets to hit, and each target has a "Target.js" script attached, you might have this variable on the "Player" script:

// in Javascript: var targets : Target[];

// or in C# public Target[] targets;

This creates an array which can be filled with as many "Target" references as you like. In the inspector, you'd then assign the array a size of "10", and then drag each target gameobject into the 10 slots available in the inspector.

There are limitations to using Dragged References, the major one being that they become impractical when there are many references to be made. (For example, it would be incredibly tedious to drag-assign references from each team member to every other team member in a game of football!). In these cases, it's probably better to either write some script to grab these references at runtime using the methods mentioned in the link at the top of this answer, or write an Editor Script to help you automatically build these references at edit-time.

Comment
Add comment · Show 8 · 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 runonthespot · Oct 13, 2010 at 10:34 PM 1
Share

thanks for your detailed answer Duck. In a static world, I think it's the right approach- it's just I have a 2d space shooter where objects have complex interactions with each other (depending on weapon effect), and I wont know in advance which type of ship I'm fighting against. I've found connecting up public variables like that at runtime is hairy and prone to errors. I'm considering using your method to connect all the parts of the ship to parent, writing a controller class for things like thrust/rotation and a "ship type" class that implements weapons etc. $$anonymous$$aybe something event based?

avatar image runonthespot · Oct 13, 2010 at 10:37 PM 0
Share

e.g. multiple planets in the system, gravity, ships may have a tractor beam that attracts (certain) other ships, particle weapons, or even an E$$anonymous$$P (which disables your enemy). I almost need to fire an event and have each ship "class" listen for it.

I realise that my case isn't the general use-case but I do prefer generic methods and probably find myself in the "rebel" group you mentioned :).

avatar image Jessy · Oct 13, 2010 at 10:53 PM 1
Share

I've been using Unity for years, and I've found Editor drag-n-drop to only cause problems and confusion in the long run. I'm not alone in this: http://unity3d.com/support/resources/unite-presentations/techniques-for-making-reusable-code

I just started using events in the past month, but it's probably been the best thing to ever happen to my program$$anonymous$$g. Everything is much more self-contained and less confusing. Highly recommended.

avatar image duck ♦♦ · Oct 14, 2010 at 06:32 AM 1
Share

I'm not suggesting that drag-references are the best option in all situations, I'm mainly stating here that it's good practice to know about this and understand it, and use it where appropriate. Also, drag references & event systems aren't mutually exclusive concepts!

avatar image duck ♦♦ · Oct 14, 2010 at 08:58 AM 1
Share

Also I'm not saying you should manually create every instance of each ship in the scene in formations for the levels. Ins$$anonymous$$d - if you have, say, 20 different kinds of ship in the entire game, each defined as a prefab, it might be an idea to have a sort of "Ship Library $$anonymous$$anager" class, which itself has a drag-reference just to each ship prefab. This "ship manager" can then instantiate them in whatever formations you like, which can be defined programatically. Because it's creating the ships, it has access to each of their instances which it can store in an array for easy direct messaging.

Show more comments
avatar image
1

Answer by runonthespot · Oct 25, 2010 at 10:30 AM

From another thread, worth reiterating here

Not quite an answer but some good reading can be had from: insomniacgames.com/assets/ cowboyprogramming.com/2007/01/05/ stackoverflow.com/questions/1901251/ Hibame 8 hours ago

from Hibame

Comment
Add comment · 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
0

Answer by runonthespot · Oct 14, 2010 at 09:21 AM

(Disclaimer- this is not an answer, but an elaboration of the question that would have been too long for a comment).

Hi Jessy, as discussed:

An example of what I'm dealing with is a scene something like the following:

-A joystick prefab and 3 GUITexture buttons that change alpha when touched. -2 (or more) spaceships, which could be one of 20 types. One of the spaceships will be user controlled and the other AI controlled. This would imply that my prefab shouldn't have the user-control code on it by default (as it may be instantiated as an AI controlled ship) so I'd expect to be able to add a script to a component at runtime? -Ships have engines (particle emitters) that respond to the "thrust" button, and turn angularly, responding to the joystick prefab. For now I've written a ship controller class that I explicitly link the buttons to and programmatically discover the engines for by enumerating children with an "engine" tag. This script also has some public properties like "thrust power" and "angular damping" -A ship will have two weapons which may be particle emitters (e.g. projectiles), one ship I've implemented abuses a gravity script to create a sort of tractor beam (and hence sucks towards it any prefab within a circular range, with the tag of "ship") -Several planets revolving around a sun (using RotateAround), currently requiring me to drag-connect "sun" to know what to rotate around. -A camera where I currently drag-connect "player" and "enemy" so that it can keep them both within the frustrum (if that's the right term?). I've recently written a method for doing this dynamically.

As you can imagine this sort of setup, being far removed from a static fps type world means that it quickly becomes messy and difficult to maintain or extend. Before I embark upon a sensible plan to get things into classes, I thought I'd ask the question you see above. I must add that while I'm reasonably familiar with normal OOP, I'm not used to the new-fangled Unity way of having multiple scripts on the same GameObject which seems to effectively remove the need for subclassing or other more complex inheritance nonsense.

I'm guessing events are really the way to go, with interfaces for the ships. I'm totally unsure as to where to put GUI handling code, and for the purposes of rapid prototyping (realising this is all disposable), I defaulted to putting it on my player directly, as it was simply the easiest way of getting a handle on the GUITexture and saved me from the trying and failing around lines of code like

(GUITexture)GameObject.Find("/SomeButton").GetComponent("GuiTexture")... 

If I were to take my C# work experience into Unity, I'd probably have setup custom events that Add ships as a listener to a Gravity effect script (say), but have no idea what the equivalent to normal C# event handling is in Unity?

Comment
Add comment · Show 2 · 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 Jessy · Oct 15, 2010 at 07:17 PM 0
Share

That's a lot of info. I don't think this is suitable for this site, and recommend moving it to the forum. Upload a tiny project or package that you think could be improved, and we can then "fix" it, upload the fixes, and describe them in a post. We can keep going back and forth, updating the project until you have enough advice to continue on your own with a more manageable system.

avatar image runonthespot · Oct 16, 2010 at 08:27 PM 0
Share

Thanks- I guess I feel unfair asking for that much help :) I'll try and get some sort of sensible structure going first and see how I go.

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

talk between C# scripts 1 Answer

What structure code is this and how can i use it with enum? 1 Answer

Two-way communication between parent and children-objects 1 Answer

Linking object functions 1 Answer

Sun and Nebula Tutorial 3 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