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 /
  • Help Room /
This question was closed Jan 17, 2016 at 02:35 AM by S_Mario86 for the following reason:

The question is answered, right answer was accepted

avatar image
0
Question by S_Mario86 · Nov 19, 2015 at 03:40 PM · c#monobehaviourclasses

Call a method of a class derived from MonoBehaviour from a class that isn't.

I'm creating a version of Minesweeper. I have a class that derives from MonoBehaviour called GameManager and a class that doesn't derive from MonBehaviour called Grid. When GameManager creates an instance of Grid, it passes itself in through Grid's constructor so that Grid will be able to call a public method in GameManager. However, whenever Grid calls a method of GameManager, Unity crashes.

Here's Grid's constructor:

 public Grid ( GameManager gm, int rowNum, int colNum, int depth, int bombCount )
     {
         m_dummy = new Cell( this, Cell.CellState.clear, false );
         m_rowNum = rowNum;
         m_colNum = colNum;
         m_depth = depth;
         m_bombCount = bombCount;
         m_cellsToClear = ( rowNum * colNum ) - bombCount;
         m_gm = gm;
 
         create ();
         init();
     }

This is where GameManager creates an instance of Grid:

 m_grid = new Grid( this, 10, 10, 10, 25 );

Here's where Grid calls the method from GameManager:

 int cRow = cell.getRow();
 int cCol = cell.getCol();
 int cDepth = cell.getDepth();
 
 m_gm.cubeCleared( cRow, cCol, cDepth );

Here's the method from GameManager that is called:

 public void cubeCleared ( int row, int col, int depth )
     {
         Destroy( getCube( row, col, depth ).gameObject );
         print( "cube cleared at "  + row + ", " + col + ", " + depth );
     }

Everything in all my scripts works well and there are no compile errors. I tried creating a very simple method in GameManager that simply prints something and calling it from Grid and Unity still crashes.

Is there something about classes derived from MonoBehaviour that doesn't let classes that aren't derived from it call their methods?

[EDIT] Upon further analysis I found the following in addition to the problem described:

The game includes an auto-clear function that will clear away any cells surrounding a cell that is clicked on and has no mines next to it. I'm implementing that with the following function:

  public void cellClear ( Cell cell )
      {
          int cRow = cell.getRow();
          int cCol = cell.getCol();
          int cDepth = cell.getDepth();
  
          m_gm.cubeCleared( cRow, cCol, cDepth );
  
          if ( --m_cellsToClear == 0 )
          {
              // you win
          }
          else if ( cell.getAdjBombNum() == 0 )
          {
              for ( int dr = -1; dr <= 1; dr++ )
              {
                  for ( int dc = -1; dc <= 1; dc++ )
                  {
                      for ( int dd = -1; dd <= 1; dd++ )
                      {
                          int r = cell.getRow() + dr;
                          int c = cell.getCol() + dc;
                          int d = cell.getDepth() + dd;
                          
                          Cell tCell = getCell( r, c, d );
                          tCell.lClick();
                      }
                  }
              }
          }
      }

The method cell.lClick() changes some states in the cell and calls cellClear() if the cell didn't have any mines and wasn't flagged. cellClear() is recursively called until there are either no more cells left to clear, or the cleared cell doesn't have any empty cells next to it. The method works when I delete the recursiveness (meaning that the auto clear functionality if taken out) or when I delete the call to GameManager (m_gm.cubeCleared).

The problem isn't an infinite loop like I had suspected when I first came across the problem as it runs fine when I delete the reference to the GameManager. It also no longer appears to be the call to GameManager itself anymore. It's only when it tries to call GameManager as it loops through itself auto-clearing cubes.

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 S_Mario86 · Jan 17, 2016 at 02:30 AM 0
Share

I've solved my problem by creating a list of the cubes I need to clear in my Grid class and then adding to it any cube that needs to be cleared. Then in my Game$$anonymous$$anager class's Update method, I take one item from the list and clear it per update cycle. That way it destroys an object once per update and doesn't slow the system down. It also frees me up to do any effects on the objects being destroyed.

1 Reply

  • Sort: 
avatar image
0

Answer by _Game_Dev_Dude_ · Nov 19, 2015 at 03:45 PM

I am not really sure why the editor is crashing. You can try looking into the unity log and see what it is saying. Either way this is not the best way to do this in my opinion. In my opinion it would be better for you to add delegates to your Grid class that the GameManager would then subscribe to and act upon them.

https://msdn.microsoft.com/en-us/library/ms173171.aspx

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 S_Mario86 · Nov 19, 2015 at 04:52 PM 0
Share

I've played around with it some more, and it seems I was mistaken in my initial analysis of the problem. There's a second part to the problem I didn't mention as I hadn't considered it part of the problem. I'll update the original post with the details as well as include them here.

I'm creating a version of $$anonymous$$inesweeper. That game includes an auto-clear function that will clear away any cells surrounding a cell that is clicked on and has no $$anonymous$$es next to it. I'm implementing that with the following function:

 public void cellClear ( Cell cell )
     {
         int cRow = cell.getRow();
         int cCol = cell.getCol();
         int cDepth = cell.getDepth();
 
         m_gm.cubeCleared( cRow, cCol, cDepth );
 
         if ( --m_cellsToClear == 0 )
         {
             // you win
         }
         else if ( cell.getAdjBombNum() == 0 )
         {
             for ( int dr = -1; dr <= 1; dr++ )
             {
                 for ( int dc = -1; dc <= 1; dc++ )
                 {
                     for ( int dd = -1; dd <= 1; dd++ )
                     {
                         int r = cell.getRow() + dr;
                         int c = cell.getCol() + dc;
                         int d = cell.getDepth() + dd;
                         
                         Cell tCell = getCell( r, c, d );
                         tCell.lClick();
                     }
                 }
             }
         }
     }

The method cell.lClick() changes some states in the cell and calls cellClear() if the cell didn't have any $$anonymous$$es and wasn't flagged. cellClear() is recursively called until there are either no more cells left to clear, or the cleared cell doesn't have any empty cells next to it. The method works when I delete the recursiveness (meaning that the auto clear functionality if taken out) or when I delete the call to Game$$anonymous$$anager (m_gm.cubeCleared).

The problem isn't an infinite loop like I had suspected when I first came across the problem as it runs fine when I delete the reference to the Game$$anonymous$$anager. It also no longer appears to be the call to Game$$anonymous$$anager itself anymore. It's only when it tries to call Game$$anonymous$$anager as it loops through itself auto-clearing cubes.

avatar image S_Mario86 · Nov 19, 2015 at 07:10 PM 0
Share

@Game_Dev_Dude

To test my theory on what the problem is I created a new empty project an put in the following two very simple pieces of code.

 using UnityEngine;
 using System.Collections;
 
 public class Game$$anonymous$$anager : $$anonymous$$onoBehaviour {
 
     Test t;
 
     // Use this for initialization
     void Start () 
     {
         t = new Test( this, 1000 );
     }
     
     // Update is called once per frame
     void Update () 
     {
         if ( Input.Get$$anonymous$$ouseButtonDown( 0 ) )
         {
             t.recursiveTest();
         }
     }
 
     public void test ()
     {
         print( "I'm doing something." );
     }
 }

 public class Test 
 {
     private int m_testNum;
     private Game$$anonymous$$anager m_gm;
 
     public Test ( Game$$anonymous$$anager gm, int testNumber )
     {
         m_gm = gm;
         m_testNum = testNumber;
     }
 
     public void recursiveTest ()
     {
         for ( int i = 0; i < m_testNum; i++ )
         {
             m_gm.test();
         }
     }
 }
 

If I set the testNumber to 100, then there's no problems. I click anywhere on the screen and the result is instantaneous. If I increment it to 1000, then Unity sits unresponsive for a bit and then is able to follow through. If I set it to 10000, then Unity crashes. From this test I gather that what I'm doing is hanging up Unity for enough time that it crashes. The question now is why does it hold up Unity for so long?

Follow this Question

Answers Answers and Comments

36 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

Related Questions

Using StartCoroutine in a Nested Class 0 Answers

Multiple PowerUps (One ItemBox) 0 Answers

NullReferenceException: Object reference not set to an instance of an object in Singleton class. 1 Answer

Test for cube with tag "Player" touch cube with tag "Finish", then switch scene to "Lvl2" 0 Answers

Class extension (player.STR to player.Stats.STR) 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