If your interface implementations differ only in the data they return from these getters, you might not need interfaces at all but a type object.
Then your platform script might be just an attachment point to glue this data structure to the game object:
public class Platform : MonoBehaviour {
public PlatformProperties platformType;
}
And your PlatformProperties could be a ScriptableObject to make it easy to author in the editor and share between instances:
[CreateAssetMenu(fileName = "newPlatformProps.asset", menuName = "Level/Platform Properties")]
public class PlatformProperties : ScriptableObject {
public Vector3 someProperty;
// etc...
}
(You can of course use private serializable fields and getters to keep these things read-only if you want to enforce clean OOP here)
Determining whether the new platform is the same type as the old platform will still require getting a handle to the new platform — I can't tell you if "what's in the box" is the same as what's in my hand unless I open the box first.
But, we can at least detect whether we have a new box to open, rather than re-peeking into the same box every frame.
First, we cache the last platform collider and script we encountered:
Collider _lastCollider;
Platform _lastPlatform;
void OnCollisionEnter(Collision hit) {
Then in your collision handling logic (be it an OnCollisionEnter or a raycast/other test)...
// Do things like discarding non-foot collisions
// and updating grounded state here.
if(hit.collider == _lastCollider) {
// no news, early-out.
return;
}
// Look for a platform script on the new platform
var platform = hit.collider.gameObject.GetComponent<Platform>();
if(platform == null)
return; // Not a platform.
_lastCollider = hit.collider
if(platform.platformType != _oldPlatform.platformType) {
// Here we know it's a new type.
}
_oldPlatform = platform;
// ... etc