playMaker

Author Topic: How to get what Physics Material a game object has?  (Read 1232 times)

EmilyAnimator

  • Playmaker Newbie
  • *
  • Posts: 3
How to get what Physics Material a game object has?
« on: June 03, 2020, 08:40:35 AM »
I am trying to use this "Get Physic Material Properties" action I got from the ecosystem. I want to use it to get the properties of physics materials on an array of game objects I will be passing to it. But, it seems like there is something wrong because no matter what I set the Game object to, it does not change what physics material it is reading.

so I have Physics material A on Game object A, and I set this action's game object slot to game object A, you would think it would load up Physic Material A, but it just stays as the "none" default Physic material, it doesn't get Physic Material A. so Its getting all the properties of "None" instead of Physic Material A.

At the end of the day, what I need to do is make an FSM that iterates over an Array of game objects, that all have different physics materials on them, and gets the physics material properties from them (I can give more context if you want but this is already long so I will leave it at that for now). so if there is a better way of doing that, please let me know!

I tried making a custom action but I am stumped on that too because there is no variable type "FsmPhysicMaterial"

Here is the action I was trying to use from the Ecosystem:
// (c) Copyright HutongGames, LLC 2010-2020. All rights reserved. 
// License: Attribution 4.0 International(CC BY 4.0)
// __ECO__ __PLAYMAKER__ __ACTION__

using UnityEngine;

namespace HutongGames.PlayMaker.Actions
{
   [ActionCategory(ActionCategory.Material)]
   [Tooltip("Gets the various properties of a Physics Material.")]
   public class GetPhysicMaterialProperties : FsmStateAction
   {
      [Tooltip("The GameObject that the material is applied to. Requires a Collider components")]
      [CheckForComponent(typeof(Collider))]
      public FsmOwnerDefault gameObject;

      [Tooltip("alternativly, can set directly, without a reference of the gameobject. Leave to null if targeting the gameobject")]
      public PhysicMaterial physicsMaterial;

      [Tooltip("Get the dynamicFriction value")]
      [UIHint(UIHint.Variable)]
      public FsmFloat dynamicFriction;

      [Tooltip("Get the staticFriction value")]
      [UIHint(UIHint.Variable)]
      public FsmFloat staticFriction;

      [Tooltip("Get the bounciness value")]
      [UIHint(UIHint.Variable)]
      public FsmFloat bounciness;

      [Tooltip("Get the frictionCombine value")]
      [UIHint(UIHint.Variable)]
      [ObjectType(typeof(PhysicMaterialCombine))]
      public FsmEnum frictionCombine;

      [Tooltip("Get the bounceCombine value")]
      [UIHint(UIHint.Variable)]
      [ObjectType(typeof(PhysicMaterialCombine))]
      public FsmEnum bounceCombine;

      [Tooltip("Repeat every frame. Useful if the value is animated.")]
      public bool everyFrame;

      GameObject _go;
      Collider _col;
      PhysicMaterial _mat;

      public override void Reset()
      {
         gameObject = null;
         physicsMaterial = null;

         dynamicFriction = null;
         staticFriction = null;
         bounciness = null;
         frictionCombine = null;
         bounceCombine = null;

         everyFrame = false;
      }
      
      public override void OnEnter()
      {
         DoGetMaterialProperties();
         
         if (!everyFrame)
         {
            Finish();
         }
      }
      
      public override void OnUpdate()
      {
         DoGetMaterialProperties();
      }
      
      void DoGetMaterialProperties()
      {
         if (physicsMaterial != null) {
            _mat = physicsMaterial;
         } else {
         
            _go = Fsm.GetOwnerDefaultTarget (gameObject);
            if (_go == null) {

               return;
            }

            _col = _go.GetComponent<Collider> ();
            if (_col == null) {
               return;
            }
            _mat =    _col.material;
         }
            
         if (!bounceCombine.IsNone)
         {
            bounceCombine.Value = _mat.bounceCombine;
         }

         if(!bounciness.IsNone)
         {
            bounciness.Value = _mat.bounciness;
         }

         if (!dynamicFriction.IsNone)
         {
            dynamicFriction.Value = _mat.dynamicFriction;
         }

         if (!frictionCombine.IsNone)
         {
            frictionCombine.Value = _mat.frictionCombine;
         }

         if (!staticFriction.IsNone)
         {
            staticFriction.Value =_mat.staticFriction;
         }

      }
   }
}

Thore

  • Sr. Member
  • ****
  • Posts: 480
Re: How to get what Physics Material a game object has?
« Reply #1 on: June 03, 2020, 09:52:24 AM »
Check whether you use the standard (3D) suite, or the 2D one (colliders 2d, Rigidbody2d etc), you also need to use a matching action, or likewise in your code.

For reading variables like this, you don't need an Fsm... property. You can get it the usual way, which might be sufficient for your case, i.e. like it's in this script:

Code: [Select]
public PhysicMaterial physicsMaterial;
And then access it as usual.

If you want to store the material like a FSM variable, you apparently have to cast it as the type (I only found this out earlier today, so it's not super tested and may not be the best way to do this).

Code: [Select]
public FsmObject fsmObject;
PhysicMaterial physicsMaterial;

And then something like this (check the component etc).

Code: [Select]
var myGameObject = Fsm.GetOwnerDefaultTarget(gameObject);
if (myGameObject == null) return;

var theCollider = myGameObject.GetComponent<Collider???>();

physicsMaterial = theCollider.material;
fsmObject.Value = physicsMaterial;

and to do the reverse (in a different action) to read a FsmObject as a PhysicsMaterial, you could try this:

Code: [Select]
public FsmObject fsmObject;
PhysicMaterial physicsMaterial;

...

physicsMaterial = (PhysicsMaterial)fsmObject.Value;

This odd construction passes the fsmObject back into a PhysicsMaterial type, and you can then use it again the usual way, e.g. to get the properties.

But I did something like this only earlier today, and I am more of a newbie when it comes to code, but maybe that helps.
« Last Edit: June 04, 2020, 04:50:19 AM by Thore »

EmilyAnimator

  • Playmaker Newbie
  • *
  • Posts: 3
Re: How to get what Physics Material a game object has?
« Reply #2 on: June 03, 2020, 06:52:35 PM »
Thanks for replying!

I understand most of this, but I am just confused about the last line, you have something called theMaterial --I am not sure what that is or where it would connect to? (and it throws an error) I know you said "something like this" so it was meant to be taken as a general example. but what is that "theMaterial" supposed to be? is that a variable to hold the final result? and if so where and how do I declare it?

thanks again!

Thore

  • Sr. Member
  • ****
  • Posts: 480
Re: How to get what Physics Material a game object has?
« Reply #3 on: June 04, 2020, 04:47:32 AM »
I made a typo. I’ll correct it.

The crucial bits are these:

Code: [Select]
fsmObject.Value = physicsMaterial;
sets PhysicsMaterial into fsmObject. And with fsmObject.Value you can access it, as with any other variable.

Code: [Select]
PhysicsMaterial physicsMaterial = (PhysicsMaterial)fsmObject.Value;
This gets PhysicsMaterial out of the object again. Bracket before fsmObject.Value is the trick. Of course that’s convenience:  (PhysicsMaterial)fsmObject.Value.bounciness etc should give you access to the physicsmaterial properties.
« Last Edit: June 04, 2020, 04:50:42 AM by Thore »