0
\$\begingroup\$

I am making a game where a player will jump into another object called land and everytime the player lands or collides with it, a score will be given, now my problems is that my method has a loophole since for every collision a score will be given therefore if a player jumps on the same land everytime score would be added up. What are the ways of assigning attributes to the object in order to prevent the loophole from happening? Can ScriptableObject be used to solve this issue?

This is my code for spawning object

foreach (var currobj in currentObject) {
         float objectYpos = -7.14f;
         Vector3 objectPos = currobj.transform.position;
         newObjPos.y = objectYpos;
         newObjPos.x = currobj.transform.position.x;

         objectPos = Vector3.Lerp(objectPos, newObjPos, 6f * Time.deltaTime);
         currobj.transform.position = objectPos;

         if (currobj.transform.position.x < playerLocation.x - objectoffsetX) {
             rmbObjects.Add(currobj);
         }
     }
     foreach (var rmv in rmbObjects) {
         currentObject.Remove(rmv);
         Destroy(rmv);
     }
 }

 private void ObjectSpawn() {
     playerLocation = playerObject.transform.position;
     spawnLocX = Random.Range(playerLocation.x + offsetSpawnX, playerLocation.x + maxdistance);
     GameObject spawned = (GameObject)Instantiate(objectList[indexLevel]);
     spawned.transform.position = new Vector2(spawnLocX, 9); //spawn object in out of view
     currentObject.Add(spawned);
 }

My code for adding score

 private void OnCollisionEnter2D(Collision2D collision)
 {

    if (collision.gameObject.tag == "land" && !onGround)
    {
        scoreManager.AddScore(2);
    }
 }
\$\endgroup\$
  • \$\begingroup\$ Friendly PSA: Use collision.gameObject.CompareTag(“land”) for better performance \$\endgroup\$ – Ed Marty Aug 31 '18 at 0:37
  • \$\begingroup\$ @EdMarty Really? What a small tweak, I never knew about that. How do you test it? \$\endgroup\$ – Shulz Aug 31 '18 at 2:22
  • \$\begingroup\$ I’m not sure what you mean about testing it, but here is Unity’s documentation on it: docs.unity3d.com/ScriptReference/GameObject.CompareTag.html \$\endgroup\$ – Ed Marty Aug 31 '18 at 6:13
  • \$\begingroup\$ I mean how can you say that gameObject.tag=='name' is faster than CompareTag(). \$\endgroup\$ – Shulz Aug 31 '18 at 6:30
  • \$\begingroup\$ I don’t have the numbers here, but the method CompareTag has been optimized specifically for this purpose. Importantly, it doesn’t make a heap allocation, but it also does the comparison in fewer IL instructions, being mostly implemented in native code, and as a handy side effect will print a warning to the console if the string you are checking against is not actually a defined tag. It may not even need to do a full string comparison in native code, due to the nature of tags, but I am only speculating at this point. \$\endgroup\$ – Ed Marty Aug 31 '18 at 12:31
1
\$\begingroup\$

The ScriptableObject is likely not what you are looking for here. You usually use it when you need a custom type of asset for your game which live in your project folder and which can be assigned to variables of game objects.

You could add a MonoBehaviour to your Land game object which handles the land collision mechanic and simply removes itself from the game object after the player collided with it.

public class Land : MonoBehaviour {

    void OnCollisionEnter(Collision collision) {
         if (collision.gameObject.CompareTag("Player")) {
                 // do what needs to be done
                 scoreManager.AddScore(2);
                 // remove this script from the game object
                 Destroy(this);
         }
    }
}

This would make sure every land can only award points once, unless you re-add the Land behaviour with AddComponent.

Note that OnCollisionEnter will only get triggered when both the Land and the Player have a Rigidbody (which you want to set to "is Kinematic" if you don't want lands to be affected by physical forces) or if the Land is set to static and the player has a Rigidbody. See the Unity collision matrix for details.

\$\endgroup\$
  • 1
    \$\begingroup\$ I thought OnCollisionEnter would be called as long as at least one of the two participating objects has a Rigidbody. I don't think they both need one. (See the static collider vs rigidbody collider cells in the collision matrix) \$\endgroup\$ – DMGregory Aug 30 '18 at 23:51
  • \$\begingroup\$ I really thought Destroy(this) would include destroying the gameobject that's why I never tried this. I'm really new haven't gone more than 300hrs in coding unity. \$\endgroup\$ – Shulz Aug 31 '18 at 2:36
  • \$\begingroup\$ @Shulz Destroy(this) only removes the current component. If you want to remove the whole object from the game, you use Destroy(this.gameObject). \$\endgroup\$ – Philipp Aug 31 '18 at 6:39
  • \$\begingroup\$ @DMGregory That's why I wrote "or if the Land is set to static and the player has a Rigidbody" \$\endgroup\$ – Philipp Aug 31 '18 at 6:40
  • \$\begingroup\$ Ah, the "static" referred to in that doc doesn't mean the static flags set in the inspector. It just means the state of not having a rigidbody attached to a collider. So "if the player has a Rigidbody" is a sufficient condition here. \$\endgroup\$ – DMGregory Aug 31 '18 at 11:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.