Rotate an object around a point in unity - unity3d

I'm new to Unity. So just for an experiment, I want to create a canon by attaching a rectangle to a circle and when the up arrow key is pressed, the canon change firing angle. So I have a rectangle object that is a sub object of a circle. And then I created a script in C# for the circle object.
Here is the codes that I have:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private float rotation = 0f;
private float timeValue = 0.0f;
public GameObject wheele;
private float xMin = -1.0f, xMax = 1.0f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
{
if (rotation >= -90)
transform.Rotate(new Vector3(0.0f, 0.0f, rotation));
rotation -= 2;
Mathf.Clamp(rotation, -90.0f, 0);
}
if(Input.GetKeyDown(KeyCode.DownArrow))
{
if (rotation >= -90)
transform.RotateAround(wheele.transform.position, Vector3.up,20);
rotation += 2;
Mathf.Clamp(rotation, -90.0f, 0);
}
}
}
I tried both transform. Rotate method, but it rotate around the center of the rectangle. But we need the rectangle to rotate with the axis, the center of the circle.

You're asking how to get the pivot point changed, right? Make an empty game object and drag the cannon under it to make it a child, then drag the cannon to a point which you think is fine and rotate the empty game object instead of the cannon, which pretty much just changes the pivot point

There are two main ways.
Update your model to set the pivot point exactly where you want it to rotate. This is how you would do this using blender. This would require you to actually create a model for the canon though (even if it's as simple as the one you've used Unity primitives for)
Create a parent GameObject, and rotate it instead. You can offset the cannon inside this GameObject, to compensate for the pivot point set on the model.

Related

Unity3D - Move camera perpendicular to where it's facing

I'm adding the option for players to move the camera to the sides. I also want to limit how far they can move the camera to the sides.
If the camera was aligned with the axis, I could simply move around X/Z axis and set a limit on each axis as to how far it can go. But my problem is that the camera is rotated, so I'm stuck figuring out how to move it and set a limit. How could I implement this?
using UnityEngine;
[RequireComponent(typeof(Camera))]
public class CameraController : MonoBehaviour
{
Camera cam;
Vector3 dragOrigin;
bool drag = false;
void Awake()
{
cam = GetComponent<Camera>();
}
void LateUpdate()
{
// Camera movement with mouse
Vector3 diff = (cam.ScreenToWorldPoint(Input.mousePosition)) - cam.transform.position;
if (Input.GetMouseButton(0))
{
if (drag == false)
{
drag = true;
dragOrigin = cam.ScreenToWorldPoint(Input.mousePosition);
}
}
else
{
drag = false;
}
if (drag)
{
// Here I want to set a constraint in a rectangular plane perpendicular to camera view
transform.position = dragOrigin - diff;
}
}
}
Transform in Unity comes with a handy Transform.right property, which regards the object's rotation. To move your camera sideways you could further utilize Lerp to make the movement smooth.
transform.position += transform.right * factor
moves an object to the right.
Use factor to adjust the desired distance and by doing so you can also set limits. Negative factor would mean moving left by the way:) Hope that helps!
It can be tricky to deal with constraints on rotated objects. The math behind this includes some vector/rotation math to figure out the correct limits relative to the object's orientation, and whether you've exceeded them.
Luckily though, Unity gives you some shortcuts to skip this math: Transform.InverseTransformPoint() and Transform.TransformPoint()! These two methods allow you to transform a point in world space into a point in local space, and vice versa.
That means that no matter how your camera is oriented, you can interpret a position from the orientation of the camera - and with just a couple extra steps, your X/Z constraints are usable because you can calculate X/Z from the camera's point of view.
Let's try to adapt your current script to use this:
using UnityEngine;
[RequireComponent(typeof(Camera))]
public class CameraController : MonoBehaviour
{
// Set the X and Z values in the editor to define the rectangle within
// which your camera can move
public Vector3 maxConstraints;
public Vector3 minConstraints;
Camera cam;
Vector3 dragOrigin;
bool drag = false;
Vector3 cameraStart;
void Awake()
{
cam = GetComponent<Camera>();
// Here, we record the start since we'll need a reference to determine
// how far the camera has moved within the allowed rectangle
cameraStart = transform.position;
}
void LateUpdate()
{
// Camera movement with mouse
Vector3 diff = (cam.ScreenToWorldPoint(Input.mousePosition)) - cam.transform.position;
if (Input.GetMouseButton(0))
{
if (drag == false)
{
drag = true;
dragOrigin = cam.ScreenToWorldPoint(Input.mousePosition);
}
}
else
{
drag = false;
}
if (drag)
{
// Now, rather than setting the position directly, let's make sure it's
// within the valid rectangle first
Vector3 newPosition = dragOrigin - diff;
// First, we get into the local space of the camera and determine the delta
// between the start and possible new position
Vector3 localStart = transform.InverseTransformPoint(cameraStart);
Vector3 localNewPosition = transform.InverseTransformPoint(newPosition);
Vector3 localDelta = localNewPosition - localStart;
// Now, we calculate constrained values for the X and Z coordinates
float clampedDeltaX = Mathf.Clamp(localDelta.x, minConstraint.x, maxConstraint.x);
float clampedDeltaZ = Mathf.Clamp(localDelta.z, minConstraint.z, maxConstraint.z);
// Then, we can use the constrained values to determine the constrained position
// within local space
Vector3 localClampedPosition = new Vector3(clampedDeltaX, localDelta.y, clampedDeltaZ)
+ localStart;
// Finally, we can convert the local position back to world space and use it
transform.position = transform.TransformPoint(localConstrainedPosition);
}
}
}
Note that I'm somewhat assuming dragOrigin - diff moves your camera correctly in its present state. If it doesn't do what you want, please include details on the unwanted behaviour and we can sort that out too.

Circle Collider Slides on Box Collider when Velocity is slowing down?

I am trying to create a carrom 2D game for learning, i added box colliders 2D all sides and for striker circle collider 2D, and set physics material for all as friction 0 and bounciness 1. and Linear Drag to 1 for stiker.
It all works fine when velocity of impact of striker with sides but velocity is slow its dragging on slides instead of bouncing. where am i doing it wrong?
I am not sure what the problem is but seems like something to do with how the engine is resolving the physics. Try resolving the collision for the individual carrom tokens manually when they hit a surface instead of relying on physics material.
Here is a simple 2D example:
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
public class ReflectingObject : MonoBehaviour {
[Range(0f, 1f)]
public float bounciness = 1;
private Rigidbody2D m_Rb;
void Awake() {
m_Rb = GetComponent<Rigidbody2D>();
}
void OnCollisionEnter2D(Collision2D col) {
if(col.contactCount > 0) {
// Get the collision contact point
ContactPoint2D point = col.contacts[0];
// Get the current speed of this object
float speed = m_Rb.velocity.magnitude;
// Get the direction where this object is heading to
Vector2 oldDirection = (Vector2)m_Rb.velocity.normalized;
// Get the reflected direction
Vector2 newDirection = Vector2.Reflect(oldDirection, point.normal).normalized;
// Calculate new velocity based on bounciness
Vector2 newVelocity = newDirection * speed * bounciness;
// Assign the velocity
m_Rb.velocity = newVelocity;
}
}
}
Something like this.
Assign this Component to the objects which you want to reflect on collision.

Cannot freeze rotation on an object that has translate function on it

I'm building a game, same as the games where rockets follows a plane to destroy it. I have a problem at the rocket. It is 3D and when the game start the rocket is rotating 90 degrees and I don't understand why, and how could be fixed.
I tried to use constrains from rigidbody, in inspector, but those didn't worked.
this is the script that controls the rocket.
public class Move_missle_lookAt : MonoBehaviour
{
public Transform mTarget;
public float mSpeed ;
const float EPSILON = 0.1f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.LookAt(mTarget.position);
if ((transform.position - mTarget.position).magnitude > EPSILON)
transform.Translate(0.0f, 0.0f, mSpeed * Time.deltaTime);
}
}
It's possible that your model is oriented incorrectly to start with. So, althought it appears to be rotated, it's actually in its native orientation.
After you call LookAt(), rotate the transform by 90° to compensate.

Smooth Camera Follow with Voxel Based Sphere

I am very new to Unity and just got done yesterday following the Roller Ball example on the learn page here at Unity3d.
To practice what I have learned I wanted to try and recreate something similar using my own art and making the game different. I have been playing around with Voxel Art and I am using MagicaVoxel to create my assests. I created the walls, the ground etc.. and all is well.
Then came the player object, the sphere. I created one as close to a sphere as possible with magicaVoxel and it rolls fine. However, when using a script to have the camera follow the object it runs into issues.
If I don't constrain the Y axis then I will get bouncing and as far as the x and z axis I get kind of a Flat Tire effect. Basically the camera doesn't follow smoothly it bounces around, stop go etc...
I have tried making the collider larger then the sphere and even using the position of the collider vs the object itself. I have also tried putting the code in Update / FixedUpdate / LateUpdate. What is the proper way to fix or address something like this? Here is my scripts below:
Camera Controller:
public class CamController : MonoBehaviour {
public GameObject player;
private Vector3 offset;
void Start ()
{
// Get the distance between the player ball and camera.
offset = this.transform.position - player.transform.position;
}
void LateUpdate ()
{
this.transform.position = player.transform.position + offset;
}
}
Player Controller:
public class PlayerController : MonoBehaviour {
public float _speed;
void FixedUpdate()
{
// Get input from keyboard.
float _hoz = Input.GetAxis("Horizontal");
float _ver = Input.GetAxis("Vertical");
// Create a vector3 based on input from keyboard.
Vector3 _move = new Vector3(_hoz, 0.0f, _ver);
// Apply force to the voxel ball
this.GetComponent<Rigidbody>().AddForce(_move * _speed);
}
}
Thanks for any help in advance.
You can use the SmoothFollow Script of Unity it self for getting smooth follow of camera.
Here are the steps how you can get the script:
1) Assets->Import Package->Scripts.
2) At the dialog that appears select all the scripts, or just the smooth follow one and hit Import button.
3) Now this script is in your project, and you can attach it to the camera.
Hope this will help you...
Best,
Hardik.

Draw a Rect using GUI.DrawTexture on exactly gameobject's position Unity

I have to use the "GUI.DrawTexture(new Rect..." function to draw a rectangle on my screen(actually, it's a gradient GUI bar i got from https://www.assetstore.unity3d.com/en/#!/content/19972, but deep inside it's just a rectangle). I want to do it right beside a gameobject i have on my screen.
The problem is: It seems like rectangle's coordinates are not the same as a gameobjects coordinates(i have searched online and i guess it's true). I have tried the function below to convert a gameobject's position to a rectangle's coordinates but still no luck:
public Vector2 WorldToGuiPoint(Vector2 position)
{
var guiPosition = Camera.main.WorldToScreenPoint(position);
guiPosition.y = Screen.currentResolution.height - guiPosition.y;
return guiPosition;
}
My best strike was when i did this:
Vector3 gameObjectsPosition = Camera.main.WorldToScreenPoint(gameObject);
And then when i wanted to draw the rectangle i did:
GUI.DrawTexture(new Rect(gameObjectsPosition.x, Screen.height - gameObjectsPosition.y, Background.width * ScaleSize, Background.height * ScaleSize), Background);
But still, the Rect isn't on the exact gameObject's position. It's x is right but y don't and when i searched the internet, they said I only had to do the "Screen.height - gameObjectsPosition.y" when drawing the Rect. It didn't work for me, the y is still wrong.
What should i do to create a rectangle that's like, right beside a current gameobject on screen (like, if the gameobject's position is x = -401 and y = -80, i want it on y=-80 and x=-300)
You need to use Screen.height instead of
Screen.currentResolution.height
using UnityEngine;
using System.Collections;
public class GuiPosition : MonoBehaviour
{
public Vector2 WorldToGuiPoint(Vector3 GOposition)
{
var guiPosition = Camera.main.WorldToScreenPoint(GOposition);
// Y axis coordinate in screen is reversed relative to world Y coordinate
guiPosition.y = Screen.height - guiPosition.y;
return guiPosition;
}
void OnGUI()
{
var guiPosition = WorldToGuiPoint(gameObject.transform.position);
var rect = new Rect(guiPosition, new Vector2(200, 70));
GUI.Label(rect, "TEST");
}
}
I've just tested attaching that MonoBehaviour to a Cube GameObject and it works