Rotate an object according to terrain in Unity (C#) - c#

I currently have an item placement system for building. It works by instantiating a "ghost" of the object that shows where it can be placed, the ghost (semi-transparent) object is attached to the camera and instantiates the object in its place when the player clicks.
I get the position at which to keep the ghost object like so:
var pos = transform.position + transform.forward * placeDistance; // A position 'someDistance' in front of the player
pos.y = Terrain.activeTerrain.SampleHeight(pos); // Get the position at the surface of the terrain to place the object
firePlaceable.transform.position = pos + Vector3.up * 0.001f; // 'halfHeight' is used in case the pivot is not on the base
Now.. I need the object to rotate according to the terrain so that the fire place is placed more or less correctly rotated. Any ideas? What would the best plan be?

Use the terrain normal vector at the place' position.
For example you could do a raycast straight down from the fireplace. The resulting hit contains a normal that is your place' up vector.
By thinking of it... I assume you already doing a raycast to get the position to place the fireplace right?
Use the placement raycast to get the up vector instead of making a new one.
So basicly do
fireplace.transform.up = clickPlaceHit.normal;

Related

In a 3D monogame project, how do I place an object a set distance in front of the camera?

I am working on a monogame project in which the player controls a ship in space (first person) and shoot asteroids that are spawned at random locations with random velocity. When I shoot, I want to place my bullet object 1.5 units directly in front of my camera no matter where the camera is or which direction it is facing. I have tried this line
Vector3 torpedoPos = CameraPosition + CameraDirection * 1.5f;
as these two posts suggest: Placing objects right in front of camera, Placing an object in front of the camera, but as soon as my position is anything other (0, 0, 0) the object is placed in the same location no matter what direction I am facing. In the line of code I posted, torpedoPos is the position I want to spawn my bullet object, CameraPosition is the current position of the camera object in 3d space and CameraDirection is a unit vector with the direction the camera object is facing.
I solved this issue with this line of code
Vector3 torpedoPos = CameraPosition + Vector3.Transform(Vector3.Forward, Orientation * 1.5f);
The orientation is the matrix which holds which direction my ship is facing. By doing a transform with the orientation * 1.5 and Vector3.Forward, I get an amount to add to my current position that will place the torpedo directly in front of the ship.

Get Unity Blend Tree to update based on player rotation (mouse position)

I'm working on the animations for a character in a top down game. I got the animations to work when the player is moving forwards towards the top, however, whenever I rotate the player with the mouse (to aim) the forward animation is now left/right, etc, etc. I'm using Unity3d and C# with blend tree animations.
The code I'm using is straightforward:
animator.SetFloat("VelX", playerInput.Horizontal);
animator.SetFloat("VelY", playerInput.Vertical);
I can't figure out how to make the forward animation play whenever I'm moving TOWARDS the mouse position.
My Solution:
var heading = Input.mousePosition - this.transform.position;
var distance = heading.magnitude;
var dir = heading / distance;
animator.SetFloat("VelX", playerInput.Horizontal * Mathf.Cos(dir));
animator.SetFloat("VelY", playerInput.Vertical * Mathf.Sin(dir));
Any help would be appreciated.
You may have figured this out already but I just had the same issue and I just found out a way to do this. Hopefully it helps others.
Vector3 inputVector = (Vector3.forward * Input.GetAxis("Vertical")) + (Vector3.right * Input.GetAxis("Horizontal"));
Vector3 animationVector = _playerModel.transform.InverseTransformDirection(inputVector);
var VelocityX = animationVector.x;
var VelocityZ = animationVector.z;
this._playerAnimator.SetFloat("x", VelocityX);
this._playerAnimator.SetFloat("z", VelocityZ);
I my case I have my movement script on a parent empty object. This object rotates the child player model, which is the one getting animated. If you do this then you will need to reference the player model like I am doing. Otherwise you can you transform if you are using the parent object.
I am using a character controller on my parent object not a rigidbody, but it may work the same either way.
From my understanding the key part is 'InverseTransformDirection' which is taking my physical world horizontal and vertical vectors and then converting them based on the rotation of my player model. This then makes the movements be relative to the players rotation rather than the worlds rotation and I can move backwards or strafe correctly as I am moving my mouse for rotation and wasd for movement.

Positioning a gun at a constant place

I am trying to position my gun the way most fps games position it,
for example like this:
But I'm having a problem when I try to position and rotate it with the player. The gun doesn't rotate well and doesn't have the same position always.
Is there a way to keep a gun in the same position and make it rotate well with the player?
But my main problem is the position of the gun i need it to stay in one place like in every fps, when i start the game and pick a gun it spawn in diffrent location on the screen Because of the rotation.
Here's is the code that I am trying to use:
GameObject temp = GameObject.Find(gameObject.name);
playerGuns[keyPress] = Instantiate(temp, Player.transform.position
+ new Vector3(-2f, 3f, 4f), Quaternion.identity) as GameObject;
playerGuns[keyPress].name = gameObject.name;
playerGuns[keyPress].tag = gameObject.tag;
playerGuns[keyPress].transform.parent = Player.transform;
playerGuns[keyPress].transform.rotation.SetLookRotation(Player.transform.position);
Alright here is the answer I promised:
First issue was with how you were setting your rotation, SetLookRotation takes in 2 parameters, Vector3 view, and Vector3 up the second is defaulted to Vector3.up. You were passing in the player.transform.position, for the "view" which is the direction you want transform to look in. Think of it like this, if I am far east facing west, my weapon will face east... (That is assuming the SetLookRotation normalizes it.) this is because my actual position is east, from some arbitrary origin. Something you could have used would have been player.transform.forward.
To spawn an object and have it have the same relative rotation and and position you can use Instantiate like you have in your original code. There are Several versions of instantiate.
In the comments I said to give yourself an offsetPosition and a eulerAngle, but this can be quite troublesome if you have multiple weapons. I mentioned I would give a recommendation for how I would set this up for multiple weapons... So here yea go.
Scriptable Objects,
In Unity you can create this objects to store information about a particular object, so for example a "Weapon" object can look like this:
using UnityEngine;
using System.Collections;
[CreateAssetMenu(fileName = "New Weapon", menuName = "Weapon")]
public class WeaponObject : ScriptableObject {
public string objectName = "New Weapon";
public Vector3 offSetPosition;
public Vector3 startOffsetRotation;
public float fireRate;
// Using a gameObject to store the weapon model so you can technical
// store the firing point.
public GameObject weaponModel;
}
You can create a new object now by right-clicking in your asset directory and going to create->weapon. Once you have done this you can rename the object it made, and the inspector will show all the public fields for this object you can modify.
With this you can create multiple weapons, and store their data in like a WeaponManager, that spawns every weapon. with something like:
WeaponObject weapon = WeaponManager.getWeapon(keyPress);
playerGuns[keyPress] = Instantiate(weapon.weaponModel, Player.transform.position + weapon.offsetPosition, Quaternion.identity) as GameObject;
playerGuns[keyPress].name = weapon.objectName;
playerGuns[keyPress].transform.parent = Player.transform;
playerGuns[keyPress].transform.eulerAngles = weapon.startOffsetRotation;
if(player.weaponScript != null) {
// we can have a single script for all of our weapons, and the WeaponObject
// will control its firerate, which projectiles it fires, etc.
player.weaponScript.setWeapon(weapon);
}
playerGuns[keyPress].transform.parent = Player.transform;
This line might be causing a problem. If you are parenting your gun to the players transform then it will follow the player. But it sounds like you want it to follow the camera?
try:
playerGuns[keyPress].transform.parent = Camera.main.transform;
Here is a useful answer provided by reddit user Mathias9807:
Many games will clear the depth buffer before drawing the gun model.
This will prevent the gun model from clipping through geometry but it
can look a bit weird when standing near a wall:
If you just want to render an object sticking to the camera you should
just get rid of the view matrix (Assuming you're using model-, view-
and projection matrices).
Explanation: Normally when you are using a view matrix (the camera matrix),the objects in the scene are being translated relative to the magnitude of the cameras position vector, and rotating by its yaw and pitch, which gives the illusion of a camera moving in a 3D space, but really there is no camera, just the objects in the scene that scale, and translate in in relation to the values defined for the camera.
So, when you remove that camera matrix for an object, the cameras position now has no influence on the models position, or put another way, the model does not move relative to the camera anymore but moves congruently with the camera.

Display Object in front of player without considering its rotation

I can show another object in front of my player using this simple line of code
newPosition =player.transform.position+player.transform.forward * distance
but how can i restrict it to always show in the same position(but in front of player) no matter what is the rotation of my player?
When you rotate gameobject transform.forward always changes.Because of you are using local values. But you need the use word values for this.
newPosition =player.transform.position+Vector3.forward * distance

How to rotate a GameObject around another object according to the mouse cursor position in C#

I'm trying to rotate an object based on mouse cursor movement(like bubble gun in bubble shooter game). But I'm Filed to do that with my script.
MY script is :
mouse_pos = Input.mousePosition;
Debug.Log(mouse_pos);
object_pos = Camera.main.WorldToScreenPoint(target.position);
mouse_pos.x = mouse_pos.x - object_pos.x;
mouse_pos.y = mouse_pos.y - object_pos.y;
angle = Mathf.Atan2(mouse_pos.y, mouse_pos.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0, 0,-angle);
It rotates only its same position it won't move.
Please any one help me to solve this. Or point me to any good tutorial ....
If I understand your problem correctly, then the object's transform is rotating around it's local origin, which is why you are seeing the correct rotation but no translation.
Unity applies transformations in the following order: scale, translate, rotate.
The easiest way to solve the problem is to parent your object's transform to another parent transform and rotate the parent transform instead (having applied a translation to your object's transform). Note that you will have to modify any scaling or translation on your object's transform because it will now be inheriting the parent transform's rotation.
Hope that helps, otherwise please provide more detail on your problem.

Categories

Resources