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
0
Question by HicorySauce · Dec 28, 2020 at 06:17 AM · movementprefabprefab-instanceinstantiation

Accessing instance of prefab from its own script

Hi, I'm trying to build a turn-based game in which a player can build units and move them around on subsequent turns. I'm doing this by instantiating the different kinds of units from prefabs, and having the different kinds of units all implement the same interface, so I can access their different behaviors from their own scripts.

I'm having trouble accessing the prefab's own instance from its script. This is probably an easy fix but I just don't know it - I've been breaking my game for hours trying to figure it out lol. Here's the script for a unit "Runner" that handles what I mentioned. It has a lot more code but I think the problem is exemplified in this sample.

 public class Runner : MonoBehaviour, ICharacter
 {
     private Tile currentTile;
 
     private void Start()
     {
         currentTile = TileManager.FindTile(this.transform.position);
     }

As you can see, "this.transform.position" is not what I would like it to be: it's accessing the prefab's position, not the instance's, so the FindTile method returns as null. Is the only way to fix my issue to assign a GameObject to the "Runner" class and assign it to its instance on instantiation? This seems unnecessarily clunky. Thanks a bunch.

Comment
Add comment · Show 9
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 sacredgeometry · Dec 29, 2020 at 05:39 PM 1
Share

What do you mean by:

"I'm having trouble accessing the prefab's own instance from its script."

A prefab doesn't have an intrinsic position. Its a configuration of gameobjects/ components that you use to more easily instantiate them.


If you have values that are consistent across multiple instances of a class (i.e. you change it once and it changes everywhere) then the member is static and shouldn't be.

avatar image HicorySauce sacredgeometry · Dec 31, 2020 at 01:42 AM 0
Share

I mean that elsewhere in my game logic (another script) I've instantiated the prefab. Each unit of the same type (instantiated from the same prefab) has the above script attached to it. I'd like to be able to move the unit around (or access its position, etc.) from said script.

avatar image sacredgeometry HicorySauce · Jan 01, 2021 at 09:48 PM 1
Share

You should be able to. Does your prefab have a hierarchy? are you accidentally testing the relative position of a child in said hierarchy instead of the prefabs root game objects position?

Show more comments
Show more comments
avatar image Michael_Berna · Jan 01, 2021 at 09:52 PM 0
Share

Does gameObject.transform.position work better for you than this.transform.position?

Another thing, as a friendly recommendation, depending on the scope of your game and the number of characters being spawned, it may be good to instantiate via addressables. They allow you to easily store a reference to the prefab, but don't force you to have it in memory. Regular references store the object in memory even when not instantiated. Addressables on store an address/reference to the item.

If you have some idea of what objects will be built, it may make sense to do object pooling where you enable and disable the object from a pool. It all depends on your scope.

avatar image sacredgeometry · Jan 01, 2021 at 10:08 PM 0
Share

Is this what you are trying to do?

https://www.youtube.com/watch?v=_qt-DavUo8U&ab_channel=sacredgeometry

avatar image HicorySauce sacredgeometry · Jan 01, 2021 at 11:59 PM 0
Share

Thanks for taking the time to make that video. I'll explain what I'm trying to do with the example you've given: imagine each of these gameobjects (the three balls) had a script attached to them that did some work. Let's say, for the sake of simplicity, all it did was print their position to the log. Normally such a method would be dead simple to write:

 public void WritePosition()
 {
 Debug.Log(this.transform.position);
 }

Yet, when I try to call this method from another script, it tries to access the prefab's transform, not the instance's transform. Here's how I've tried to set things up to avoid this: when I select the Tile my desired unit is on, I save that Tile's gameobject in my pointer's selector script. then I access the gameobject's method by calling it as whateverItsNameIs.WritePosition(). But this doesn't work either.

The only way I can get this to work is to make the WritePosition method (for example) to take a gameobject as an argument; then, in the pointer's selector, to pass in the gameobject when it calls that gameobject's method.

1 Reply

· Add your reply
  • Sort: 
avatar image
1

Answer by TimBur · Dec 31, 2020 at 01:54 AM

The keyword you're looking for is 'this'. It's actually a C# keyword, and it's a reference to the self-object.

Ex:

  • this.transform = {stuff};

  • this.Start();

  • this.currentTile

    Note that 'this' doesn't point to a prefab. It points to an instance of a Monobehavior on an instantiated object. So once a prefab is instantiated, the Runner behavior on that instantiated object can act on itself using 'this.'

    You can also use the keyword 'gameObject' with a lower-case 'g' to refer to the GameObject that the script is attached to.

Comment
Add comment · Show 5 · 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 HicorySauce · Dec 31, 2020 at 01:58 AM 0
Share

Hi Timbur, thanks for taking the time to reply. Unfortunately, your comment doesn't solve my issue. You can see I did in fact use the keyword "this" in my sample code shown above, when trying to locate the position of the object my instantiated prefab.

The real problem at hand is what "this" is pointing to. It is not pointing to the instantiation of the prefab - it is pointing to the prefab itself. If I try to run Destroy(this) on my runner script, for example, it throws an error saying that it can't destroy assets for safety; for the specific issue I'm having on this script, its transform's position is null, since it doesn't exist.

avatar image TimBur HicorySauce · Dec 31, 2020 at 02:44 AM 0
Share

You're right, I didn't read your code, or the words after your code. Apologies. That said, I think the question in the title of this post isn't asking after what you're actually looking for. Having read your words more carefully, I have some maybe helpful ideas.

First, the keyword 'this' always points to a code-type thing. A prefab is a GameObject, and so 'this' will never point to a prefab. You might try using the debugger, setting a breakpoint at the CurrentTile = line, and looking at the value of 'this'.

Your Runner class is a $$anonymous$$onobehavior, which means it is a Component. In Unity, all Components (like your Runner) must be attached to a GameObject. Also, all GameObjects have a Transform component. When you say this.transform, the 'this' refers to the Runner instance, and 'transform' refers to the Transform component that is attached to this same GameObject. So 'this.transform' is getting a sibling component, the component attached to the same GameObject as the Runner script. Which probably isn't what you are asking for.

You asked "Is the only way to fix my issue to assign a GameObject to the "Runner" class and assign it to its instance on instantiation?" $$anonymous$$aybe. Sort of. If you want Runner to be a $$anonymous$$onobehavior, then yes. You must create a GameObject, and attach a Runner Component to it. That isn't necessarily bad. I often write a Level$$anonymous$$anager-type component, and attach it to a GameObject. That GameObject doesn't do anything other than sit invisibly in the level, but it keeps me organized, and it gives the Level$$anonymous$$anager access to useful $$anonymous$$onobehavior-type methods (Start, Update, etc.). The full list of $$anonymous$$onobehaviour methods is here)

If Runner doesn't need $$anonymous$$onobehavior methods, you can remove the $$anonymous$$onobehavior inheritance from your class definition. You could have Runner inherit from ScriptableObject instead, or just have a vanilla C# class. Neither ScriptableObjects nor vanilla classes require attachment to a GameObject.

But going back to the core of the issue. What is it that you want the Runner class to do? What do you want to do with CurrentTile? If you could talk more about this, I might be able to help better.

avatar image HicorySauce TimBur · Jan 01, 2021 at 09:08 PM 0
Share

Hi - thanks for the reply. I'm pretty sure the "this" in this instance points to the prefab itself - like I said, I can't run destroy(this) in my code because it tells me it can't delete something from the assets folder.

I actually do already have a few "managers" attached to an empty game object - I'll kind of explain my game's architecture to help you understand what I'm having trouble with. I have a Tile $$anonymous$$anager which keeps track of which tiles have units on them, which player they belong to, etc., and a Turn $$anonymous$$anager which keeps track of whose turn it is. A player builds and makes actions with units, and the player's actions send signals to the Tile and Turn managers.

Here's where I'm having trouble. Let's say one player has built a "runner" on a tile, and the same player tries to access this unit on a following turn. The player checks the tile manager to see if it's the player's unit. Then, the "runner" itself, using the script sampled above, sends to the player a list of tiles on which it can act (in this case, move to). The runner then moves to one of these tiles. However, the runner is not moving towards the tile, because the "this" keyword doesn't refer to itself, just the prefab.

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

196 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Script stopped working, prefabs behaving strangely 0 Answers

GameObject variable points to instance instead of prefab when prefab gets instantiated 2 Answers

Making a bubble level (not a game but work tool) 1 Answer

Show transparent version of prefab before instantiation 1 Answer

Using Resources.load with a variable 1 Answer


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