Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

Need help recalculating volume each time it's changed

Discussion in 'Scripting' started by stobak, Jan 20, 2020.

  1. stobak

    stobak

    Joined:
    Dec 9, 2016
    Posts:
    16
    Hello! Right now I have a simple script that makes my player grow each time it comes into contact with an object that has less volume than itself. Here is how it stands so far.


    Code (CSharp):
    1. {
    2.  
    3.     private BoxCollider playerCollider;
    4.     public float playerVolume;
    5.     public float growthRate;
    6.     public float otherVolume;
    7.  
    8.  
    9.   // On Start, calculate the player's initial volume
    10.     void Start()
    11.     {    
    12.         playerCollider = GetComponent<BoxCollider>();
    13.         Vector3 geometry = playerCollider.bounds.size;
    14.         playerVolume = geometry.x * geometry.y * geometry.z;
    15.  
    16.     }
    17.  
    18.  
    19.     // Behavior when player collides with other collider
    20.     void OnTriggerEnter(Collider other)
    21.  
    22.     {
    23.         // calculate volume of the other collider
    24.         Vector3 geometry = other.bounds.size;
    25.         float otherVolume = geometry.x * geometry.y * geometry.z;
    26.  
    27.         // Player's new volume is re-calculated
    28.         playerVolume = otherVolume * growthRate + playerVolume;
    29.  
    30.         // If player volume is greater than the object it collides with, grow
    31.         if (playerVolume > otherVolume)
    32.         {
    33.             transform.localScale += new Vector3(1, 1, 1) * growthRate;          
    34.  
    35.         }
    36.  
    37.     }
    38.    
    39. }

    Right now I'm not quiet getting the desired result. My character will grow in volume regardless of the volume of anything else it comes into contact with (larger or smaller). I have some debug.logs inserted throughout to see what's updating in the unity editor. The local scale of my object seems to update, but not the playerVolume. I think the problem is that I need a custom method that calculates the volume. I then need to call it on start and every time I want to recalculate it...Problem is, I'm not entirely sure how to go about that. Could anyone give me an example of how to go about this?

    I'm still learning, so any advice or tips are appreciated!
     
  2. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    241
    Suppose the player has volume 2, the other is larger and has volume 3, and growthRate is 0.5.
    It becomes
    playerVolume = 3 * 0.5 + 2
    playerVolume = (3 * 0.5) + 2
    playerVolume = 1.5 + 2
    playerVolume = 3.5

    So even though the player was smaller, you're still increasing its value just by doing the calculation
     
    Last edited: Jan 20, 2020
  3. stobak

    stobak

    Joined:
    Dec 9, 2016
    Posts:
    16
    Yikes! that makes a lot of sense. Any ideas on how to remedy this? A script example would be very helpful.
     
  4. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    241
    I mean it depends on how you use growthRate, but if its a difficulty modifier, like the player has to be 10% bigger than the thing to absorb it, growthRate would be 0.1f:

    Code (CSharp):
    1. var volumeToBeat =otherVoulme + (otherVolume * growthRate);
    2. if(playerVolume > volumeToBeat){
    3. //grow
    4. }
    But probably you mean growthRate to be what percent of the enemy to grow by, right?
    Code (CSharp):
    1.  
    2. if(playerVolume > otherVoulme ){
    3. playerVolume += otherVolume * growthRate
    4. }
     
  5. stobak

    stobak

    Joined:
    Dec 9, 2016
    Posts:
    16
    Exactly! I plugged this in to test, but I'm still getting weird results. Right now I'm starting with a test cube for the player it's dimensions are:

    x = 2
    y = 2
    z = 2

    So my volume shows up as 8 when I click start. When I collide with another cube that has these dimensions:

    x = 1
    y = 1
    z = 1

    (So a volume of 1). My cube grows to a new volume of 9, which is incorrect. The inspector will show my new cube has dimensions of:

    x = 3
    y = 3
    z = 3

    So my test cube's volume should have actually changed to 27. Is there a way to update this so that it's correct after every collision?
     
  6. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    241
    Re-post your OnTriggerEnter()
     
  7. stobak

    stobak

    Joined:
    Dec 9, 2016
    Posts:
    16
    Code (CSharp):
    1. void OnTriggerEnter(Collider other)
    2.  
    3.     {
    4.         Vector3 geometry = other.bounds.size;
    5.         float otherVolume = geometry.x * geometry.y * geometry.z;
    6.  
    7.         if (playerVolume > otherVolume)
    8.         {
    9.             playerVolume += otherVolume * growthRate;
    10.             transform.localScale += new Vector3(1, 1, 1);          
    11.         }
    12.  
    13.     }
     
  8. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    241
    Code (CSharp):
    1. void OnTriggerEnter(Collider other)
    2.     {
    3.         var playerCollider = this.GetComponent<Collider>();
    4.      
    5.         Vector3 otherGeometry = other.bounds.size;
    6.         Vector3 playerGeometry = playerCollider.bounds.size;
    7.      
    8.         float otherVolume = geometry.x * geometry.y * geometry.z;
    9.         float playerVolume =  playerGeometry.x * playerGeometry.y * playerGeometry.z;    
    10.      
    11.         if (playerVolume > otherVolume)
    12.         {
    13. var relativeSizeOfOtherThing = otherVolume/playerVolume;
    14.             transform.localScale += Vector3.One * relativeSizeOfOtherThing * growthRate;
    15.         }
    16.     }
     
    Last edited: Jan 20, 2020
  9. stobak

    stobak

    Joined:
    Dec 9, 2016
    Posts:
    16

    Thanks for this! still no luck, unfortunately. Here's how everything looks so far. maybe there's something I missed?


    Code (CSharp):
    1. {
    2.  
    3.     private BoxCollider playerCollider;
    4.     public float playerVolume;
    5.     public float growthRate = .02f;
    6.     public float otherVolume;
    7.  
    8.  
    9.     void Start()
    10.     {
    11.         playerCollider = GetComponent<BoxCollider>();
    12.         Vector3 geometry = playerCollider.bounds.size;
    13.         playerVolume = geometry.x * geometry.y * geometry.z;
    14.  
    15.     }
    16.  
    17.     void OnTriggerEnter(Collider other)
    18.     {
    19.         var PlayerCollider = this.GetComponent<Collider>();
    20.  
    21.         Vector3 otherGeometry = other.bounds.size;
    22.         Vector3 PlayerGeometry = playerCollider.bounds.size;
    23.  
    24.         float otherVolume = otherGeometry.x * otherGeometry.y * otherGeometry.z;
    25.         float playerVolume = PlayerGeometry.x * PlayerGeometry.y * PlayerGeometry.z;
    26.  
    27.         if (playerVolume > otherVolume)
    28.         {
    29.             var relativesizeofotherthing = otherVolume / playerVolume;
    30.             transform.localScale += Vector3.one * relativesizeofotherthing * growthRate;
    31.         }
    32.  
    33.     }
    34.  
    35. }
     
  10. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    241
    Well the logic works, just this was wrong of me:
    var relativesizeofotherthing = otherVolume / playerVolume;
    so just take that out and replace the reference to relativeSizeOfOtherTHing with a reference to otherVolume.
     
  11. stobak

    stobak

    Joined:
    Dec 9, 2016
    Posts:
    16
    Apologies. I'm not quite sure what you mean
     
  12. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    241
    Change
    Code (CSharp):
    1.             var relativesizeofotherthing = otherVolume / playerVolume;
    2.             transform.localScale += Vector3.one * relativesizeofotherthing * growthRate;
    To
    Code (CSharp):
    1.             //var relativesizeofotherthing = otherVolume / playerVolume;
    2.             transform.localScale += Vector3.one * otherVolume * growthRate;
    And one of them needs a rigibody
     
    Last edited: Mar 12, 2022
  13. stobak

    stobak

    Joined:
    Dec 9, 2016
    Posts:
    16

    Thank you! I just plugged it in and the player growth works as expected. I really appreciate all your help thus far. The only thing remaining is that the playerVolume no longer updates in the inspector. My cube always shows a volume of 8 regardless of how large I get. Is there a way to update that during run time?
     
  14. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    241
    I made a local variable to hold the result of the volume calculation whenever theres a collision. Because before, remember, just by doing the calculation it was increasing the playerVolume. So, unfortunately the local playerVolume is overriding the class level one, you could change either ones name, then set the class-level one whenever the player localscale is actually changed
     
    Last edited: Jan 20, 2020
    stobak likes this.
  15. stobak

    stobak

    Joined:
    Dec 9, 2016
    Posts:
    16
    Got it! I'll give it a go. Thanks again for all your help!
    Kind of off topic, but could you recommend any online resources to get a better grasp on C# as it relates to game development? I realize a lot of my problems stem from just being ignorant on the structure of the language.
     
  16. stobak

    stobak

    Joined:
    Dec 9, 2016
    Posts:
    16
    @vestigial
    Just wanted to chime back in here with an update. I have everything working wonderfully now. Just wanted to express my gratitude for helping me out. Here is the script I ended up with:


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class IncreaseMass : MonoBehaviour
    6. {
    7.     private BoxCollider playerCollider;
    8.     public float playerMass;
    9.     public float otherVolume;
    10.     public float growthRate;
    11.  
    12.  
    13.     void Start()
    14.     {
    15.         CalculateVolume();
    16.     }
    17.  
    18.     void CalculateVolume()
    19.     {
    20.         playerCollider = GetComponent<BoxCollider>();
    21.         Vector3 geometry = playerCollider.bounds.size;
    22.         playerMass = geometry.x * geometry.y * geometry.z;
    23.     }
    24.  
    25.     void GrowLarger()
    26.     {
    27.       transform.localScale += Vector3.one * growthRate;
    28.     }
    29.  
    30.     void OnTriggerEnter(Collider other)
    31.     {
    32.         Vector3 otherGeometry = other.bounds.size;
    33.         Vector3 playerGeometry = playerCollider.bounds.size;
    34.  
    35.         float otherVolume = otherGeometry.x * otherGeometry.y * otherGeometry.z;
    36.         float playerVolume = playerGeometry.x * playerGeometry.y * playerGeometry.z;
    37.  
    38.         if (playerVolume > otherVolume)
    39.         {
    40.  
    41.             GrowLarger();
    42.  
    43.         }
    44.     }
    45.  
    46.     void Update()
    47.     {
    48.         CalculateVolume();
    49.     }
    50.  
    51. }
    52.  
     
  17. stobak

    stobak

    Joined:
    Dec 9, 2016
    Posts:
    16
    I do appreciate the importance of refactoring so I'd welcome any suggestions on how to clean it up. I'm pretty early on in creating this experience, so the less technical debt I have the better.