Reputation: 79
Following this tutorial (its a bit back in Godot 3) and I have run into some issues with PhysicasRayQueryParameters2D
. Here is the code from the video:
if (ableToShoot)
{
var spaceState = GetWorld2D().DirectSpaceState;
Godot.Collections.Dictionary result = spaceState.IntersectRay(this.Position, player.Position, new Godot.Collections.Array {this} );
if (result != null)
{
if (result.Contains("collider"))
{
if (result["collider"] == player)
{
GD.Print("Shooting");
ableToShoot = false;
shootTimer = shootTimerReset;
}
}
}
}
And here is my code:
if (ableToShoot)
{
var spaceState = GetWorld2D().DirectSpaceState;
//Change 1
var query = PhysicsRayQueryParameters2D.Create(this.Position, player.Position);
query.Exclude = new Godot.Collections.Array<Rid> { };
query.CollisionMask = 1;
Godot.Collections.Dictionary result = spaceState.IntersectRay(query);
if (result != null)
{
if (result.ContainsKey("collider")) //Change 2
{
if (result["collider"] == player) //Error Message
{
GD.Print("Shooting");
ableToShoot = false;
shootTimer = shootTimerReset;
}
}
}
The code from the video is obviously different due to the changes form Godot 3 to 4. However, I am not entirely sure if the corrections/changes I have made are the correct ones. I am still new to both C# and Godot. I marked the two places I made changes so that it is easier to compare. My main issue however is that I keep getting an error message where it says result["collider"] == player
.
That is how it was in the tutorial, and I did it myself but I get an error when I do, saying that I cannot use the '==' opperators when applyed to a Variant
and PlayerController
(a class from a different script). I tried casting result into a PlayerController
, but once the tile's started blocking between me and the enemy I started getting error messages saying that I cannot convert Godot.TileMap
to Godot.PlayerController
. What should I do instead? And are there any other mistakes I have made when translating the code?
I looked over many reddit forms and the Godot documentation but I could not get over that last error.
Upvotes: 0
Views: 608
Reputation: 16574
Godot.Variant
is a struct that can hold one of many types of values, including native C# types (strings, integers, arrays of basic types, etc) and a collection of internal Godot types. While there are a bunch of different implicit type conversions (i.e. the compiler tries to figure out what type you need and calls the appropriate type conversion method on Variant
), you often need to explicitly extract something from a Variant
before you can work with it.
(The full list of types you can find in a Variant
is here.)
In this case, the collider
value from IntersectRay
's result dictionary is a GodotObject
which you can do equality comparisons on... once C# knows what type it is.
There are a couple of ways to go about this using conversion operators, the As*()
methods such as AsObject()
and so on. Here are a couple of options that might work for you:
Variant.AsObject()
:
if (result["collider"].AsObject() == player)
{
}
Explicit cast:
if ((GodotObject)result["collider"] == player)
{
}
Implicit cast to variable:
GodotObject? collider = results["collilder"];
if (collider == player)
{
}
And finally, there's the Obj
member which will fetch the internal value as a c# object?
which you can do reference comparisons on.
Obj
reference comparision:
if (ReferenceEquals(results["collider"].Obj, player))
{
}
This isn't an exhaustive list, but hopefully one of those will work for you. Using ReferenceEquals()
works in most cases and bypasses any operator overloaing of equality for situations where you really don't need anything other than a reference compare, which is both faster and (all too often) more immediately understandable.
Upvotes: 2