Grappling hook ray cast direction problems in Unity - c#

Hey team I'm currently working on a 3rd person game where I would like to fire grappling hooks from the player to a point that is offset from the center of the camera.
I have a screen overlay canvas with Ui images for crosshairs. When the left shift is held down the crosshairs move outward from center along the x axis and return to center once shift is released, a bit like crosshair spread in games except I want to trigger the spread via the shift key. These crosshairs are meant to dictate the location the anchors of the grappling hook land, originating from the player and hitting whatever object is directly forward of the crosshairs. (imagine attack on titan ODM gear if you've seen it). I am looking for a way to ray cast from the player to the point forward of these crosshairs while they're offset from the center.
So far I have the grappling system set up and working but am having trouble with the direction parameter when I use the crosshair spread. It separates fine but where the hooks land in relation to the cross hairs are obviously out as I'm trying to use angle calculations at the moment instead of what is forward of these reticles.
I'm basically wondering if it is possible to use these screen overlay UI images to cast forward from or if there's a better way to accomplish the same thing. I have my doubts because they're screen overlay so I imagine their coordinates wont be attached to the camera as they appear.
Thanks in advance for your help.

What I would do is determine the location of the reticleson the screen, then (as Aybe suggested) use ScreenPointToRay or ViewportToRay (depending on if it's easier to get a pixel position or a fractional position of each reticle) to Physics.Raycast that ray from the camera into the scene to find where the rays collide. At this point, you have two world positions the player seems to want to shoot the hooks.:
Vector3 hookTarget1;
Vector3 hookTarget2;
So, now you actually have to fire the hooks - but as you know the hooks aren't being shot from the camera, they are being shot from the player, and they maybe offset by a bit. Let's call the originating points (which may have the same value):
Vector3 hookOrigin1;
Vector3 hookOrigin2;
So, then you can create Rays that originate from the hook origins and point at the targets:
Ray hookShot1 = new Ray(hookOrigin1, hookTarget1 - hookOrigin1);
Ray hookShot2 = new Ray(hookOrigin2, hookTarget2 - hookOrigin2);
Using these rays, you can do another Physics.Raycast if you would like, to confirm that there aren't any trees or other obstacles that are between the player and the target location - and if there are, that may be where the anchor should actually sink:
Vector3 anchorPoint1;
Vector3 anchorPoint2;
The segment between the origin of these rays and these anchor points would be appropriate for rendering the cable, calculating physics for how to move the player, as well as checking for collisions with world geometry that might cause the anchor to release.

Related

How to calculate the 3D vector perpendicular to a polygon surface in a specific direction

I'm creating an asteroid mining game in Unity 3D, where "down" is the center of the planet you are on (So I am mostly using local rotations when dealing with vectors). I have a working physics-based character controller, but it has problems dealing with slopes. This is because when I add a force to the character, currently it pushes along the player's forward vector (see picture). What I want to do is calculate the vector that is parallel to this terrain surface, but in the direction that the player is facing (so that the player can move up the slope).
I originally thought that i could just find the vector perpendicular to the normal, but then how do I know which direction it will be in. Also complicating matters is the fact that the player could be oriented in any way in relation to the global x, y, and z.
Either way, I have the surface normals of the terrain, I have all of the player's directional vectors, but I just can't figure out how to put them all together. I can upload code or screenshots of the editor if necessary. Thanks.
The usual way is to factor out the component of the forward vector that is parallel to the surface normal:
fp = f - dot(f, n) * n
See vector rejection.
This formulation will also make fp shorter the steeper the slope is. If you don't want that, you can re-scale fp afterwards to have the same length as f.

Unity C# make camera sway back and forth while keeping direction

I've seen other threads that want to make turrets rotate back and forth, however my question is more complicated because I want to allow the player to control his/her camera while the sway is affecting it. This is to simulate the feeling of recoil when the player gets hit by an attack.
Ideally, I'd like to have the sway first up-right then down-left and gradually return to center using something like Mathf.Sin(timer * Time.deltaTime * scalar)
I've been able to get the camera to sway using Quaternion functions but when doing so, the camera becomes level with the ground until the sway is complete, or the player is locked facing north while the camera shakes.
What code can I use to perform the tasks above?
My camera instance is named mainCamera,
The way I've done this in the past is to have a GameObject that the camera is a child of.
Position and rotation of the parent will affect the child relative to the parent, but the player can still have control over the camera itself. You can then have the parent node swaying, but without the code on it clashing with the camera itself moving and rotating based upon player interaction.

XNA Monogame Mouse Projectile Click

I am coding for a game and I have it running fine and all, but I ran into the issue of projectiles. I have no idea of how to calculate the mouse position and send a projectile over. I've looked though many stackoverflow tutorials and many youtube videos, but they are either too vague or very very complex. Could someone please explain the process? I have been coding in C# for 2 years now, so I do have background knowledge. Please Help!
Well, you don't tell what kind of game you are working on and what the projectile you want to "send over", whatever that means but here are a few pointers, maybe one will help:
#1: If you are doing a 2D game, and you want to send a projectile from some point toward the mouse cursor, then you simply get the position of the mouse by calling GetState() on your MouseState instance, and reading it's X and Y properties, then get the direction of the projectile by subtracting the location of the origin of the projectile from the mouse position. Then you can move the projectile along that line by storing the time you launched it, subtracting that every frame from the actual time to get how long it has been on its way and then adding that many times it's speed times the normalized direction to its origin coordinates.
Example:
For this I assume you have a Projectile class that has Vector2 field called origin, one called direction, one called position, a float called speed and an int called startTime and you have an instance of it with origin and speed already set. Modify as necessary for your actual code.
MouseState ms = new MouseState();
in your Update method:
ms.GetState();
projectile.direction = new Vector2(ms.X, ms.Y) - projectile.origin;
projectile.direction.Normalize();
projectile.position = projectile.origin + projectile.speed * (gameTime.TotalGameTime.TotalMilliseconds - projectile.stratTime) * projectile.direction;
And then in the Draw method you just draw the projectile to the coordinates in projectile.position.
#2: You are doing a 3D game and want to shoot a projectile originating from your camera and directed toward whatever your mouse is pointing at. You will need to generate a Ray with something like this:
private Ray getClickRay(Vector2 clickLocation, Viewport viewport, Matrix view, Matrix projection)
{
Vector3 nearPoint = viewport.Unproject(new Vector3(clickLocation.X, clickLocation.Y, 0.0f), projection, view, Matrix.Identity);
Vector3 farPoint = viewport.Unproject(new Vector3(clickLocation.X, clickLocation.Y, 1.0f), projection, view, Matrix.Identity);
Vector3 direction = farPoint - nearPoint;
direction.Normalize();
return new Ray(nearPoint, direction);
}
From there you can get the position of your projectile the same way as above, only using Vector3-s instead of Vector2-s.
#3: You want to simulate some sort of launcher and do a physical simulation on the trajectory of the projectile. Since I find this less likely than the first two I'll just describe the idea: you set a minimum and maximum rotation for your launcher along 2 axes, link each rotation to the ratio of the full width and length of your screen to the mouse position, and then use the angles and whatever other variables you have to calculate the direction and speed of the projectile at launch, then simulate physics each frame.
I hope one of these will help.

How do I make so when user moves the camera it doesn't go beyond the scene borders?

How do I make so when I move the camera(with touch) it doesn't go beyond the scene borders?
How do I move the camera with touch so it moves strictly with scene parts, like slides(swipe-first slide, another swipe-another slide) with not going beyond the borders of the scene?
The game I'm making has a camera like in Disco Zoo game for android (I'm a newbie)
Technically, the scene doesn't really have a border. You'll need to define the border somehow within your game, then constrain the camera's position with something like Mathf.Clamp(value, min, max) in an Update() function on the camera.
How can you define the border? It's up to you. Some ideas:
Hard-code the values in the script that clamps the camera. Probably the quickest option, but not flexible
Make public parameters on the camera script that let you set min and max positions in the X and Y directions
If you have a background image: use the extents of that to define your camera's extents
Create empty objects in your scene that define the minimum and maximum extents of the scene. Put your "min" object at the top-left, and the "max" object at the top-right. Connect it to the camera script, then use those positions to see if you've gone too far in any given direction. The main reason to do this is that it's visual.
(Slower, but dynamic) If everything in your scene uses physics, you could search the entire scene for every Collider component, then find the furthest extents in each direction. However, this is probably going to be pretty slow (so you'll only want to do it once), it'll take a while to code, and you'll probably want to tweak the boundaries by hand anyway.

Constant orbit using physics in Unity3D

I am playing around with Unity3D and adding physics to the objects in my scene. I currently have a sphere (planet) in the center of the screen, and I have another sphere (moon) positioned outside of it that is not moving. When I run the game I want the moon to orbit the planet by applying a force to it. I have been able to get the force added by calling rigidbody.AddForce() and that will move it in the specified direction but it won't orbit. I'm not sure how to add force to it so that it will continuously orbit the sphere at a constant velocity.
I've tried some examples using a ConfigurableJoint and it orbits, but it starts out bouncing a little and then starts the orbit. My goal is to have a bunch of orbiting moons orbiting at their own speed that are able to bounce off eachother but not lose their velocity.
Any ideas?
Generally speaking you will fail, eventually, because rounding errors in your integration method will slowly throw you out of orbit. You can get very close in the ways suggested, but you could consider doing something more like the Kerbal Space Program, which seems to precalculate the orbit as an ellipse and then follow that ellipse until it has a reason to believe it should stop, rather than strictly "simulating" the orbit ...
If a collision occurs, allow normal physics to resolve the collision, and then recalculate your new orbit based on the result and start following that.
For the moon to orbit you would need to give the moon an initial velocity. Then have it accelerate towards the planet, that is a constant force.
gameObject.rigidbody.AddForce(1, 0, 0);
gameObject.constantForce.relativeForce = Vector3(0, 1, 0);

Categories