- Home /
How to properly offset a Handles.DrawSolidArc by an angle in different axis?
I have spent far too long on this and I do not understand what is causing this. I have a direction vector that points forward on the Z axis. I would like for my entity to see plus or minus X degrees left or right in front of it.
This works fine the way I am doing it, but when trying to get this to work with Handles.DrawSolidArc instead of being straight, it curves in all sorts of ways, and I can't figure out why.
My code is as follows:
var forwardMinY = Quaternion.AngleAxis(-angleDegreesY, perceiver.Entity.CurrentTransform.right) * perceiver.Entity.CurrentTransform.forward;
Quaternion spreadAngle = Quaternion.AngleAxis(perceiver.senseOptics.viewOrientation, Vector3.up);
var angleNew = spreadAngle*forwardMinY;
Handles.DrawSolidArc(perceiver.Entity.CurrentTransform.position, perceiver.Entity.CurrentTransform.right, angleNew , angleDegreesY * 2,
perceiver.senseOptics.rangeMin);
What happpens (Sorry Image Upload is not working for me currently):
https://i.gyazo.com/183a71d7f02d11a3e2e17fd1fbcf7aee.png
What I want (offset in the same direction as up axis handle):
https://gyazo.com/aa953af71fc139d8794d7248dc1693d3
Thank you for your time and help!
When you say "I want to offset it by an angle on the Y axis" what exactly do you mean? To me, an angle on the Y-axis is a rotation around the Y-axis. From your image it looks like you want an arc that is in front of the entity and has its normal about the entity's X-axis. Is that correct? If so, can you clarify what the offset is supposed to be? Basically, something like "my entity can see directly in front of itself plus or $$anonymous$$us X degrees to the left/right" or "my entity can see directly in front of itself plus X degrees altitude"
Hi Adam,
Sorry for the confusion. $$anonymous$$y entity can see directly in front of itself $$anonymous$$us X degrees to the left or right, is what I want.
Its far from perfect, for i used only linear interpolations, but it fits my needs :
Vector3 calculateVector3(Vector3 targetVector3) {
if ((float)$$anonymous$$athf.RoundToInt(scriptObject.viewAngle) <= 180f) {
targetVector3 = new Vector3 (-(1f + ((0f - 1f) / (0f - 180f)) * ((float)$$anonymous$$athf.RoundToInt(scriptObject.viewAngle) - 180f)), 0f, (0f + ((1f - 0f) / (0f - 180f)) * ((float)$$anonymous$$athf.RoundToInt(scriptObject.viewAngle) - 180f)));
}
if ((float)$$anonymous$$athf.RoundToInt(scriptObject.viewAngle) > 180f) {
targetVector3 = new Vector3 (-(0f + ((1f - 0f) / (181f - 360f)) * ((float)$$anonymous$$athf.RoundToInt(scriptObject.viewAngle) - 360f)), 0f, ((-1f) + ((0f - (-1f)) / (181f - 360f)) * ((float)$$anonymous$$athf.RoundToInt(scriptObject.viewAngle) - 360f)));
}
return targetVector3;
}
//Below for the Handles use :
targetVector = calculateVector3 (targetVector);
Handles.DrawSolidArc (scriptHolder.transform.position, scriptHolder.transform.up,targetVector , scriptHolder.viewAngle, scriptHolder.viewRadius);
Answer by Adam-Mechtley · Nov 08, 2016 at 08:37 AM
The exact details will depend on exactly how your code handles your input parameters, but this is how I go about this sort of situation.
// these values would actually come from your perceiver data
// total arc of visiblity in degrees
float visibilityArc= 30f;
// how far the entity can see
float range = 2f;
Handles.DrawSolidArc (
perceiver.Entity.CurrentTransform.position,
Vector3.up,
// start from rotation that is half of entire arc of vision
Quaternion.AngleAxis(-0.5f * visibilityArc, Vector3.up) * (
// subtract out vertical component of forward-facing vector if altitude is not used in visibility test
transform.forward - Vector3.Dot(transform.forward, Vector3.up) * Vector3.up
),
visibilityArc,
range
);
Note, too, that if you're interested in making an interactive version of this handle, I have a package on the Asset Store that might have some APIs that would interest you.
Thanks for the help Adam,
For the code provided the Handles.DrawSolidArc takes a float as a second to last parameter (which is the view cone) so I cannot apply the spreadAngle there. I tried using the math to subtract out the vertical component, but I get the same results as above. Also in the code provided the arc is on the X plane rather than the Y plane.
I actually own both of your assets, Custom Handles as well as Ragdoll Workshop and do have just this solution working with them. I am trying to achieve the same thing without it in a project that does not use assets.
Actually "DrawSolidArc" is defined as:
public static void DrawSolidArc(Vector3 center, Vector3 normal, Vector3 from, float angle, float radius)
What Unity version do you use? Also keep in $$anonymous$$d that this is an editor class and can only be used inside the Editor. Apart from that the implementation is not very good ^^. It always creates a temp vector array with 60 elements, so it creates 720 bytes of garbage each time the arc is drawn. It might be better to draw the arc manually ^^.
btw: "normal" and "from" should be perpendicular to each other. Otherwise the resulting "arc" wouldn't be a flat arc, but like a sector of a "cone" (either positive or negative cone).
Sorry I updated the code example--the second to last parameter should have been visibilityArc in my example, rather than spreadAngle. Again I don't know what your exact situation is, but your post above indicated "$$anonymous$$y entity can see directly in front of itself $$anonymous$$us X degrees to the left or right", which is what this example does (where X is actually 1/2 of visibilityArc).
Sorry for some reason I never got an email response back letting me know there was a new reply.
I have tried the code and tried the changes many times editing and trying many things but the results are always the same, it is either a cone or completely flat on the X axis. I replaced the spreadAngle with the orientation (in degrees) it should be offset from forward (which was substituted for X or 1/2 the visibilityArc in the example given). The code for me currently displays flat on the X axis.
I think @Bunny83 is correct though in that the normal and from must always be perpendicular to stop the cone behavior. The problem is I can not get the math right needed to get this to work.
Answer by Bunny83 · Dec 05, 2016 at 12:09 AM
Well, if you only have a forward axis there are basically two ways you could draw the view area:
Either the arc is always flat on the ground
or the arc is elevated according to the forward axis you specify
For the first case the normal vector is simply Vector3.up since it's the world up vector so the "arc plane" is world aligned (the world x-z-plane). Unity now has a dedicated method for projecting a vector onto a plane : Vector3.ProjectOnPlane. With this is't really easy to get your forward vector down onto the x-z-plane
Vector3 newForward = Vector3.ProjectOnPlane(givenForward, Vector3.up).normalized;
For the second case you need a tilted normal vector so that your desired forward axis is inside the tilted plane. If your forward axis comes from a Transform the easiest way to get the according up vector is using transform.up. If the forward axis is elsewhere defined you can simply calculate it using the cross product. First we need the current "right" vector:
Vector3 right = Vector3.Cross(Vector3.up, givenForward);
With that right vector we can calculate the tilted up vector:
Vector3 up = Vector3.Cross(givenForward, right);
This will give you the tilted up vector that is perpendicular to the given forward vector.
Of course the starting vector "from" would simply be the forward vector rotated by half the visibility angle around the up vector:
Vector3 fromVec = Quaternion.AngleAxis(-0.5f * visibilityArc, up) * givenForward;
Now you should have everything you need:
The position
the normal vector (our "up" vector)
the starting vector (our "fromVec")
the visibility angle (visibilityArc)
and your radius
Like this:
Handles.DrawSolidArc( yourPosition, up, fromVec, visibilityArc, radius);
Your answer
Follow this Question
Related Questions
Not so much a scripting problem - Just need smart peoples' help. 2 Answers
Editor Script Handles.Label problem. Labels don't move with gameobject 1 Answer
How to read the current PivotRotation or PivotMode ? 1 Answer
Rotate object's local up towards a vector. 1 Answer
Help Understanding Script 2 Answers