How would you make game objects harvestable?

Im thinking about different strategies.

What i want are ‘trees’ that can be harvested for resources. To harvest player needs to be next to the item. This is the strategy i thought up. What do you think about it and how would you do it?

  • If tree is clicked. Check if player is close enough to the tree. If so begin harvest.
  • As long as the mousbutton is down, drain tree of resources and pass them to the player.
  • When trees resource is zero, kill the tree. Death animation followed by destruction of object.

Are those terrain trees or normal game objects?

Sorry! Normal GameObjects. I know nothing of terrain trees. Can they be scripted easily?

Normal GameObjects should work fine. Unity’s buildin terrain features are a pain in the ass to work with via scripting. As it is now, those terrains are only useful for a prebuild level design and no modifcation is done in-game.

And yes, that would be a good way on how to do that. If you want to be really cautious with performance, make sure the player decides what it detects with an interaction, not every tree on its own. (Dont use the update in the tree component, as with a lot of trees you will get a lot of update checks which are unnecessary)

You sir are a lifesaver! I was about to do just that! But you make alot of sense.Thank you.

The reason is that it is easy to use the Trees OnMouseDown method. But then i would have to check for stuf in the update method of the tree anyway.

I should have nothing in the trees update and just go with letting the tree have public methods that the player or other objects calls when interacting. So then i have to figure out how to get the object the mouse is clicking on.

You’re welcome :wink:

What you could do though in regards to the resource draining, is starting a Coroutine when you detect the interaction. You can just let the tree itself handle everything from then on, as your player script could get a bit overcrowded when you do it inside there. It’s also a good programming practice to let objects handle as much as possible on their own.

For the player interaction, you could do a Raycast from the players position and rotation for a X length. If the raycast hits something, make a SendMessage call with the name of the method you want to invoke on the tree.

Im not really understanding the Coroutine well enough. What i started to do now is using MouseEnter/Over/Down/Up and method Tree.Harvese() that is called as long as the mouse is over the tree, button is down and player is close enough. It starts from mouseOver so it can only run in one Tree at a time. How does that sound?

That should work, but I don’t know wether the OnMouseEnter etc methods cause any overhead, as it is something internal from unity. But what I mean is, instead of gathering resources from the Update function (as far as I understand, that’s what you’re doing now), you can use a coroutine. If understanding correctly, this is what you are doing now:

void Update() {
    if( MouseDown) {
        Player.AddResource( 5 );
        this.resources -= 5;
    }

    void OnMouseDown() {
         MouseDown = true;
    }

    void OnMouseUp() {
        MouseDown = false;
    }
}

Instead, you could do this:

    IENumerator Harvest() {
        while( MouseDown) {
            Player.AddResource( 5 );
            this.resources -= 5;
            if( resources < 0 ) {
                Destroy(gameObject);
                break;
            }
            yield return null; //or you could do "yield return new WaitForSeconds(2);"
        }
    }

    void OnMouseDown() {
         MouseDown = true;
        StartCoroutine( Harvest() );
    }

    void OnMouseUp() {
        MouseDown = false;
    }

The difference is that in the second approach, the tree doesn’t do any checking before it is actually interacted with

OK! I like it. So when the tree is cliked the while loop starts, but only for as long as the button is down and only as long as the tree has resources?

exactly, though you should check for enough resources first before you add them to the player :slight_smile:

Actually im thinking further away. Im doing this in a base clase and setting up your coroutine code so that it will call a virtual method called ‘IsBeingClicked’ and then calls Virtual ‘NoLongerClicked’ when mouseExits or button no longer is pressed. And then all the classes that derives can react to the mouseclicking differenlty. :smile:

Sounds good :smile: Best to use programming tricks where possible, as long as they make sense. Don’t overcomplicate things if you don’t need to though :wink:

HAH! Actually it did not go so well. System hangs every time click a tree. :stuck_out_tongue:

	IEnumerator CheckForMouseClickAndOver ()
		{
		
				while (Input.GetMouseButton(0)) {
			
						WhileBeingClicked ();
				
				}
				this.OnNoLongerClicked ();

				yield return null; //or you could do "yield return new WaitForSeconds(2);"
			
		}

	public virtual void WhileBeingClicked ()
		{
				Debug.Log ("Woho! Im being clicked!!!");
				if (IsWithinDistance (Gs.droid.gameObject, Gs.droid.reach)) {
						transform.renderer.material.color = Color.green;
				} else {
						transform.renderer.material.color = Color.red;
				}
		}

public virtual void OnNoLongerClicked ()
		{
				renderer.material.color = bodyStartColor;
		}

Move the yield return call inside the while loop. This tells unity to continue this frame with code execution

Edit: Just noticed that I had forgotten a bracket in my example code. This probably caused some confusion

AWWWWW YEEEEEEAAAH! That was it! Ok so ill use this way of doing it and now i learned about CoRoutines. THANKS!

Hey, ill buy your lazer sfx pack later. Just cause i love to check out sfx. :slight_smile:

You’re welcome :wink:

Hehe thats kind of you. Have to say that I made that a long while back though, so it’s not that great… I hope to bring out some more stuff soon

Good luck with your project! Hope to see it back in the WIP section :slight_smile: