I created a glass with reflection.
The idea is when the player is getting close to a window to see the player reflection like the player is looking on the window.
The glass reflection is working and it's disabled in the Hierarchy. I'm enabling the glass reflection later in the game.
This is a screenshot of the glass when it's turned on :
I positioned the glass to on the window :
This is the player screenshot. The player have a child name NAVI. The NAVI is positioned a bit in front of the player :
The player have a Rigidbody. In the screenshot on the left the NAVI object and in the right the player Inspector settings :
And this script is attached to the window not to the glass but to the window :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemAction : MonoBehaviour
{
public RotateCamera rotatecamera;
public GameObject glass;
public GameObject player;
public void Init()
{
player.transform.localPosition = new Vector3(transform.localPosition.x - 1, transform.localPosition.y, transform.localPosition.z);
glass.SetActive(true);
}
}
This is a screenshot of the window with the script attached to it :
The idea is when some where in the game when it's calling the method Init it will position the player as much as close to the window to see the player reflection on the glass.
But instead the player is falling down through the floor and keep falling nonstop.
You're using the window's local position to set the player's local position. Instead, use position and only change the player's x component:
float paddingDistance = 1f; // Change this to adjust the padding
player.transform.position = new Vector3(transform.position.x - paddingDistance,
player.transform.position.y,
player.transform.position.z);
The problem with this is that it only works for glass rotated in exactly such a way. If you want to make this work for any such glass orientation, you can make a plane parallel to the glass but separated some distance and move the player to the closest point on the plane. Assuming the glass is normal to its transform.left direction:
float paddingDistance = 1f; // Change this to adjust the padding
Vector3 paddingPoint = transform.position + transform.left * paddingDistance;
float paddingToPlayerAlongLeft = Vector3.Dot(transform.left,
player.transform.position - paddingPoint);
// closest point to player.transform.position on padding plane
player.transform.position = player.transform.position
- paddingToPlayerAlongLeft * transform.left;
But even this only works for one side of the glass. If you wanted to make this work for either side of the glass, you need to determine if the player's on the left side or not (we can do this using Vector3.Dot), then make the plane in the corresponding direction:
float paddingDistance = 1f;// Change this to adjust the padding
float glassToPlayerAlongLeft = Vector3.Dot(player.transform.position - transform.position,
transform.left);
float paddingLeftMod = glassToPlayerAlongLeft > 0f ? 1f : -1f;
float paddingToPlayerAlongLeft = glassToPlayerAlongLeft - paddingDistance * paddingLeftMod;
// closest point to player.transform.position on padding plane
player.transform.position = player.transform.position
- paddingToPlayerAlongLeft * transform.left;
However, even this only works if the glass is perfectly vertical. If the glass is not always vertical, then you could find the line intersection of the horizontal plane at the player's height and the padding plane and then set the player's position to the closest point on that line
Related
I am developing a VR scene using Oculus Quest. I need to place a cube in front and a few units below the user eye level. The cube has to move when the user moves. E.g. if the user turns or moves the cube user secure its position by always staying in front. How can I do this?
Should I take the OVRCameraRig position and rotation and apply that to the cube? But I read from StackOverflow question Unity3D Getting position of OVRCameraRig that OVRCameraRig doesn't move and needs to consider the CenterEyeAnchor details.
Can I extract CenterEyeAnchor rotation and position as below?
OVRCameraRig overCameraRig;
var position = overCameraRig.centerEyeAnchor.position;
var rotation = overCameraRig.centerEyeAnchor.rotation;
//OR should I use lines below?
var position = overCameraRig.centerEyeAnchor.transform.position;
var rotation = overCameraRig.centerEyeAnchor.transform.rotation;
How can I apply the extracted potion and rotation of CenterEyeAnchor to the cube gameObject if that is going to solve this problem?
I tried the following script and add it to the cube but the cube didn't move with the user movement.
Further, I see "Test position" log but no "Normal " or "Transform " logs.
public class MoveCube : MonoBehaviour
{
private OVRCameraRig overCameraRig;
public float offset = 10;
private GameObject itemObject;
private float distance = 3.0f;
// Update is called once per frame
void Update()
{
Debug.Log("Test position");
Debug.Log("Normal " +overCameraRig.centerEyeAnchor.position);
Debug.Log("Transform " + overCameraRig.centerEyeAnchor.transform.position);
if (itemObject != null)
{
itemObject.transform.position = overCameraRig.centerEyeAnchor.transform.position + overCameraRig.centerEyeAnchor.transform.forward * distance;
itemObject.transform.rotation = new Quaternion(0.0f, overCameraRig.centerEyeAnchor.transform.rotation.y, 0.0f, overCameraRig.centerEyeAnchor.transform.rotation.w);
}
}
}
The best thing to do is set the cube as a child of the player in the hierarchy.
only will that not rotate with the player, but i suspect that your camera is on your player so do this:
but this will rotate on all axes. you can also freeze its rotation using the rigidbody freeze rotation.
The Issue
I'm making a 2D Unity game where the main weapon of your character is a fireball gun. The idea is that a fireball will shoot out of the player's hand at the same angle the player's hand is pointing. I have 3 issues:
When I shoot the fireball, since the fireball is a RididBody, it pushes the player. This is because I've made the centre of the player's arm (the same place where the fireball shoots from) the point at which the arm rotates around the player (what is meant to be the shoulder);
To instantiate the fireball prefab on the arm, the only way I know how to do it is by using a piece of code which requires the arm to be a RigidBody. This means that the arm is affected by gravity and falls off the player on start unless I freeze the arm's y-axis movement, which means that when the player jumps, while the arm does not fall, it floats at the same y-position as where it started while moving along the x-axis; and
When the fireball is shot, the angle from which it is propelled after being shot is not the same angle as the angle of the player's arm.
Instantiating the Fireball
if (Input.GetKeyDown(KeyCode.Space))
{
pew.Play();
var fireballTransform = Instantiate(fireballPrefab); //creates a new shot sprite
fireballTransform.position = new Vector3(transform.position.x + horizMultiplier, transform.position.y, transform.position.z);
fireballTransform.rotation = orientation;
fireballTransform.transform.Rotate(0, 0, transform.rotation.z);
}
if (Input.GetKeyDown(KeyCode.D)) // moves right
{
orientation = 0;
horizMultiplier = 0.08F;
}
if (Input.GetKeyDown(KeyCode.A)) // moves left
{
orientation = 180;
horizMultiplier = -0.08F;
}
This piece of code is located within the script applied to the player's arm. The movement of the arm works fine and the problem seems to be either within this piece of code or the code for my fireball (which I will put next). A few definitions:
pew is a sound effect played when the fireball is shot;
horizMultiplier is the distance from the arm's centre which I would like the fireball to instantiate (also dependant of if the player) is facing left or right); and
orientation is which direction the player is facing (left or right). The fireball is then instantiated facing that same direction.
Fireball Script
public Vector2 speed = new Vector2(); // x and y forces respectively
private Rigidbody2D rb; // shorthand
private float rotation;
void Start()
{
rb = GetComponent<Rigidbody2D>(); // shorthand
rotation = rb.rotation;
if (rotation == 0)
{
rb.AddForce(Vector3.right * speed.x); // propels right
}
if (rotation == 180)
{
rb.AddForce(Vector3.left * speed.x); // propels left
}
}
I believe this code is explanatory enough with comments (if not please comment and I'll address any question). I believe an issue could also be in this piece of code because of the lines: rb.AddForce(Vector3.right * speed.x); and rb.AddForce(Vector3.left * speed.x); as these add directional forces to the object. I don't know is this is objective direction (right or left no matter what direction the object the force is being applied to is facing) or if it's right or left in terms of the object-- say if an object was rotated 90 degrees clockwise and that object had a force applied so that it moves right making the object move downwards.
What I'm expecting to happen is the player's arm will turn so that when a fireball is fired it is fired in the direction the arm is facing. The arms turning mechanics are fine, it's just trying to properly instantiate the fireball. Can anyone help with any of the issues I've laid out?
How I would go about this:
Add an empty transform as child of the arm and move it to where the fireball should spawn. Also make sure the rotation of it is such that its forward vector (the local z-axis) points to where the fireball should go. To see this, you need to set "Local" left of the play button.
Spawn the fireball at the transform's position with its rotation.
Ignore collision between the arm's/player's collider and the fireball's collider with https://docs.unity3d.com/ScriptReference/Physics.IgnoreCollision.html. If necessary, you can enable the collision between the two colliders again after 1s or so.
Set the fireball rigidbody's velocity to speed * rigidbody.forward.
If you need help with the code, please post it so I can see what's going on.
Edit:
The arm definitely doesn't require a Rigidbody.
You can just use Instantiate(prefab, position, rotation) as shorthand.
Is this for a 2D game?
Also, I'm going to sleep now but I'll gladly try to help tomorrow.
Your Issues
1) You should be masking the fireball's layer not to collide with your player's layer.
You can find more info about this here: https://docs.unity3d.com/Manual/LayerBasedCollision.html
(note: make sure you're on the Physics2D panel, and not the Physics one, as that's for 3D)
2) There is a setting called gravityScale in RigidBody2D. You should set this to 0 if you don't want gravity to be affecting your object. More info: https://docs.unity3d.com/Manual/class-Rigidbody2D.html
Fireball Instantiate
if (Input.GetKeyDown(KeyCode.Space))
{
pew.Play();
var position = hand.transform.position + hand.transform.forward * horizMultiplier;
var rotation = hand.transform.rotation;
var fireball = Instantiate<Fireball>(fireballPrefab, position, rotation);
fireball.StartMoving();
}
Fireball Script
private Rigidbody2D rb; // shorthand
private float rotation;
public float Speed;
public void StartMoving()
{
rb = GetComponent<Rigidbody2D>(); // shorthand
rb.velocity = transform.forward * Speed;
}
void OnTriggerEnter(....) { .... }
I am creating a first person controller in Unity. Very basic stuff, camera is a child of Player capsule. Codes work, but I need help explaining what's going on.
*camera is child of Player in hierarchy
These are my questions:
In PlayerMovement, why are we translating in the Z-axis to achieve vertical movement when Unity is in Y-Up axis?
In CamRotation, I have no idea what is going on in Update(). Why are we applying horizontal movement to our Player, but then vertical movement to our Camera? Why is it not applied on the same GameObject?
What is mouseMove trying to achieve? Why do we use var?
I think we are getting a value of how much mouse has been moved, but what then does applying Vector2.Scale do to it?
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour {
public float speed = 5.0f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float mvX = Input.GetAxis("Horizontal") * Time.deltaTime * speed;
float mvZ = Input.GetAxis("Vertical") * Time.deltaTime * speed;
transform.Translate(mvX, 0, mvZ);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CamRotation : MonoBehaviour {
public float horizontal_speed = 3.0F;
public float vertical_speed = 2.0F;
GameObject character; // refers to the parent object the camera is attached to (our Player capsule)
// initialization
void Start()
{
character = this.transform.parent.gameObject;
}
// Update is called once per frame
void Update()
{
var mouseMove = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
mouseMove = Vector2.Scale(mouseMove, new Vector2(horizontal_speed, vertical_speed));
character.transform.Rotate(0, mouseMove.x, 0); // to rotate our character horizontally
transform.Rotate(-mouseMove.y, 0, 0); // to rotate the camera vertically
}
}
XY is the plane for 2D Unity games. For 3D, you have Z-axis for height, and XY plane for positioning.
Note that different components from mouseMove are being applied (.x for character and .y for the camera). This means that the movement from the character is not equal to the movement from the camera; one should be faster/slower than the other.
var is a predefined C# keyword that lets the compiler figure out an appropriate type. In this case, it's the same as if you had written Vector2 as in Vector2 mouseMove = new Vector2(...);.
You are scaling the value from mouseMove, by multiplying its components by predefined values in your code. That's just it.
EDIT
You apply .x to your character because, as you commented after the line of code, you want to move it horizontally. As for the camera, .y is being applied because you want to move it vertically.
The negative value could be because the axis is inverted, so you make it negative so the camera has a natural movement. It's the same principle some games have in the setting, where they allow you to invert Y-axis.
I want to restrict player movement in the sphere, the schematic diagram show as below. If player movement is out of range, then restrict player to sphere max radius range.
How can I write C# code to implement it, like this?
These are my current steps:
Create 3D sphere
Create C# code append to sphere object
My code so far:
public Transform player;
void update(){
Vector3 pos = player.position;
}
I don't know how you calculate your player`s position but before assigning the new position to the player you should check and see if the move is eligible by
checking the new position distance form the center of the sphere
//so calculate your player`s position
//before moving it then assign it to a variable named NewPosition
//then we check and see if we can make this move then we make it
//this way you don't have to make your player suddenly stop or move it
//back to the bounds manually
if( Vector3.Distance(sphereGameObject.transform.position, NewPosition)< radius)
{
//player is in bounds and clear to move
SetThePlayerNewPosition();
}
What #Milad suggested is right but also include the fact you won't be able to "slide" on the sphere border if your movement vector even slightly goes outside the sphere :
(sorry for the crappy graphic skills...)
What you can do if you want to be able to "slide" on the sphere interior surface is get the angle formed between the player position and the X vector and then apply this angle with the :
public Transform player;
public float sphereRadius;
void LateUpdate()
{
Vector3 pos = player.position;
float angle = Mathf.Atan2(pos.y, pos.x);
float distance = Mathf.Clamp(pos.magnitude, 0.0f, sphereRadius);
pos.x = Mathf.Cos(angle) * distance;
pos.y = Mathf.Sin(angle) * distance;
player.position = pos;
}
Just make sure using this won't counter effect your player movement script (that's why I put it in LateUpdate() in my example).
I am trying to get my character to face the mouse by rotating on its y axis. It rotates a little, but it do not face the mouse. The Camera's position is directly above the player, and its in orthographic view I see many other examples of top down shooters and there almost exactly like mine so i don't know whats the problem please help thank you.
using UnityEngine;
using System.Collections;
public class playermovementscript : MonoBehaviour {
public float movementspeed = 5f;
public float bulletspeed = 10f;
public GameObject bullet;
public GameObject shooter;
public Vector3 target;
public Camera camera;
// Use this for initialization
void Start () {
//refrence to main camera
Camera camera;
}
// Update is called once per frame
void Update () {
//call movement function in every frame
movement ();
// cheek for input of f in every frame if true execute shoot function
if (Input.GetKeyDown (KeyCode.F)) {
shoot();
}
}
void movement(){
// makes refrence to gameobjects rigidbody and makes its velocity varible to equal values of axis x and y
gameObject.GetComponent<Rigidbody>().velocity = new Vector3(Input.GetAxisRaw("Horizontal")*movementspeed,0,Input.GetAxisRaw("Vertical")*movementspeed);
// makes vector 3 type target equall to mouse position on pixial cordinates converted in to real world coordniates
target = camera.ViewportToWorldPoint (new Vector3(Input.mousePosition.x,Input.mousePosition.y,camera.transform.position.y - transform.position.y));
//target.x -= transform.position.x;
//target.z -= transform.position.z;
// states the vector 3 values of target
Debug.Log (target);
// makes object local z face target and iniziates up axis
transform.LookAt (target,Vector3.up);
}
Going to make an attempt to explain what's going on...
target = camera.ViewportToWorldPoint (new Vector3(Input.mousePosition.x,Input.mousePosition.y,camera.transform.position.y - transform.position.y));
The above code is trying to convert a mouse position which is in Screen Space (which measures the position from (0,0) to the width/height of the screen in pixels) to a Viewport Space (which measure the same screen but with a different measure, it measures the positions from (0,0) to (1,1)).
In Unity
Screen Space Measurement: Origin (0,0) to the max width/height
Viewport Measurement: Origin (0,0) to (1,1)
Reference: http://docs.unity3d.com/ScriptReference/Camera.html
If you desire to still use "ViewportToWorldPoint" then you could do a "ScreenToViewportPoint" then follow it with a "ViewPortToWorldPoint".
Otherwise, you could look into using "ScreenToWorldPoint" from the start.