I want to make a code with endless 3d car game, car control by swipe left and right. without using any physics.
info.
3-lane,specific lane center (9,0,car z position),(0,0,car z position),(-9,0,car z position).
I do swipe control and move swipe control but not good.
public class playercontrol: MonoBehaviour {
public void Update() {
playera.transform.Translate((Vector3.forward * speed * Time.deltaTime));
Debug.Log("speed" + speed);
if (check == false) {
if (Input.GetMouseButtonDown(0)) {
Debug.Log("left button");
firstPressPos = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
}
if (Input.GetMouseButtonUp(0)) {
secondPressPos = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
currentSwipe = new Vector2(secondPressPos.x - firstPressPos.x, secondPressPos.y - firstPressPos.y);
currentSwipe.Normalize();
//swipe left
if (currentSwipe.x < -1.0 f && currentSwipe.y > -0.5 f && currentSwipe.y < 0.5 f) {
Debug.Log("left swipe");
if (transform.position.x > -9 f) {
spos = transform.position;
Debug.Log("spos" + spos);
endpos = new Vector3(transform.position.x - 9 f, transform.position.y, transform.position.z + ((speed * 2) / 20));
Debug.Log("speed......... ......." + ((speed * 5) / 20));
transform.rotation = Quaternion.Euler(0, -10.0 f, 0);
check = true;
//endpos * (Time.deltaTime*0.5f);
// Time.timeScale = 0.5f;
// to.rotation = Quaternion.Euler (0, 0, 0);
}
}
//swipe right
if (currentSwipe.x > 1.0 f && currentSwipe.y > -0.5 f && currentSwipe.y < 0.5 f) {
Debug.Log("right swipe");
if (transform.position.x < 9 f) {
Debug.Log("spos1" + spos);
spos = transform.position;
endpos = new Vector3(transform.position.x + 9 f, transform.position.y, transform.position.z + ((speed * 2) / 20));
Debug.Log("speed1......... ......." + ((speed * 5) / 20));
transform.rotation = Quaternion.Euler(0, 10.0 f, 0);
check = true;
// Time.timeScale = 0.5f;
// to.rotation = Quaternion.Euler (0, 0, 0);
}
}
}
}
if (check == true) {
time += 10 * Time.deltaTime;
transform.position = Vector3.Lerp(spos, endpos, time);
// transform.rotation = Quaternion.Lerp (from.rotation, to.rotation, time);
if (time > 1) {
transform.rotation = Quaternion.Euler(0, 0, 0);
//Time.timeScale = 1.0f;
//playera.transform.Rotate (0, 0, 0);
//transform.Rotate (0, 0, 0);
check = false;
time = 0;
}
}
}
}
Related
My goal for my code is to create an array of sprite in game, but 10 of the sprites are bombs. In which currently it does not do that. Currently, my if statement (I don't think) is not check for all possible guesses to get all 10 bombs.
foreach(Vector3 b in BombCords)
{
if (n && Mathf.Round(b.x * 10.0f) * 0.1f == Mathf.Round(i * 10.0f) * 0.1f && Mathf.Round(b.y * 10.0f) * 0.1f == Mathf.Round(l * 10.0f) * 0.1f) {
g = Instantiate(Bomb1, b, new Quaternion(0, 0, 0, 0));
n = false;
Debug.Log("Bomb");
t = true;
break;
}
else if (n == false && Mathf.Round(b.x * 10.0f) * 0.1f == Mathf.Round(i * 10.0f) * 0.1f && Mathf.Round(b.y * 10.0f) * 0.1f == Mathf.Round(l * 10.0f) * 0.1f) {
g = Instantiate(Bomb2, b, new Quaternion(0, 0, 0, 0));
n = true;
Debug.Log("Bomb");
t = true;
break;
}
// Debug.Log(b.x + " = " + Mathf.Round(i * 10.0f) * 0.1 + ", " + Mathf.Round(b.y * 10.0f) * 0.1f + " = " + Mathf.Round(l * 10.0f) * 0.1);
}
Right now their is 8 or 9 bombs coming up, and rarely is 10. I know that it is not instantiating the entirety 10 bombs because my Debug.Log("BOMB") only outputs the amount of bombs on the map.
using UnityEngine;
using System.Linq;
using UnityEngine.UI;
using TMPro;
using System.Collections;
using UnityEngine.EventSystems;
public class BlockStuff : MonoBehaviour {
public GameObject Floor1;
public GameObject Floor2;
public GameObject Bomb1;
public GameObject Bomb2;
public GameObject Mined1;
public GameObject Mined2;
public Vector3[] BombCords = new Vector3[10];
void Update() {
var mousePos = Input.mousePosition;
var mousePosWorld = Camera.main.ScreenToWorldPoint(mousePos);
RaycastHit2D raycast = Physics2D.Raycast(mousePosWorld, new Vector2(0, 0), 1);
RaycastHit2D braycast = Physics2D.Raycast(mousePosWorld + Vector3.down, Vector2.zero, 0);
if (Input.GetMouseButtonDown(0)) {
if (raycast.collider.gameObject.layer == 3) {
GameObject g = Mined2;
if (BombCords.Contains(new Vector3(Mathf.RoundToInt(mousePosWorld.x - 0.5f) + 0.5f, Mathf.RoundToInt(mousePosWorld.y - 0.5f) + 0.5f, 0))) {
Debug.Log("BOMB");
}
if (raycast.collider.gameObject.tag == "Floor1") {
g = Instantiate(Mined1, raycast.collider.gameObject.transform.position, raycast.collider.gameObject.transform.rotation);
raycast.collider.gameObject.SetActive(false);
} else {
g = Instantiate(Mined2, raycast.collider.gameObject.transform.position, raycast.collider.gameObject.transform.rotation);
raycast.collider.gameObject.SetActive(false);
}
g.name = "grass";
g.transform.parent = transform;
}
// raycast.collider.gameObject.transform == Mathf.RoundToInt(raycast.collider.gameObject.transform.position.x) ; //IN PROCESS OF CHANGING GRASS TO MINE FLOOR
}
}
void Start() {
bool n = true;
bool t = false;
for (int i = 0; i < 10; i++) {
var BombCord = new Vector3(Mathf.RoundToInt(Random.Range(-9.5f, 0.5f) - 0.5f) + 0.5f, Mathf.RoundToInt(Random.Range(-4f, 5f) - 0.5f) + 0.5f, -0.2f);
// for (int l = 0; l <= i; l++){
foreach (Vector3 b in BombCords) {
while (true) {
if (b == BombCord) {
BombCord = new Vector3(Mathf.RoundToInt(Random.Range(-9.5f, 0.5f) - 0.5f) + 0.5f, Mathf.RoundToInt(Random.Range(-4f, 5f) - 0.5f) + 0.5f, -0.2f);
} else {
break;
}
}
}
BombCords[i] = BombCord;
Debug.Log(BombCords[i]);
// Instantiate(Bomb1, BombCord, new Quaternion(0,0,0,0));
}
for (float l = -4.5f; l < 5.5; l += 1) {
for (float i = -10.5f; i < 0.5; i += 1) {
GameObject g = Floor1;
foreach (Vector3 b in BombCords) {
if (n && Mathf.Round(b.x * 10.0f) * 0.1f == Mathf.Round(i * 10.0f) * 0.1f && Mathf.Round(b.y * 10.0f) * 0.1f == Mathf.Round(l * 10.0f) * 0.1f) {
g = Instantiate(Bomb1, b, new Quaternion(0, 0, 0, 0));
n = false;
Debug.Log("Bomb");
t = true;
break;
} else if (n == false && Mathf.Round(b.x * 10.0f) * 0.1f == Mathf.Round(i * 10.0f) * 0.1f && Mathf.Round(b.y * 10.0f) * 0.1f == Mathf.Round(l * 10.0f) * 0.1f) {
g = Instantiate(Bomb2, b, new Quaternion(0, 0, 0, 0));
n = true;
Debug.Log("Bomb");
t = true;
break;
}
// Debug.Log(b.x + " = " + Mathf.Round(i * 10.0f) * 0.1 + ", " + Mathf.Round(b.y * 10.0f) * 0.1f + " = " + Mathf.Round(l * 10.0f) * 0.1);
}
if (n && t == false) {
g = Instantiate(Floor1, new Vector3(i, l, -0.2f), new Quaternion(0, 0, 0, 0));
n = false;
} else if (n == false && t == false) {
g = Instantiate(Floor2, new Vector3(i, l, -0.2f), new Quaternion(0, 0, 0, 0));
n = true;
}
if (t) {
g.name = "BOMB";
} else {
g.name = "grass";
}
g.transform.parent = transform;
t = false;
// if (n && BombCords.Contains(new Vector3(i,l,-0.2f))){
// g = Instantiate(Bomb1, new Vector3(i,l,-0.2f), new Quaternion(0,0,0,0));
// n = false;
// Debug.Log("Bomb");
// }
// else if (n == false && BombCords.Contains(new Vector3(i,l,-0.2f))){
// g = Instantiate(Bomb2, new Vector3(i,l,-0.2f), new Quaternion(0,0,0,0));
// n = true;
// Debug.Log("Bomb");
// }
// else if (n && BombCords.Contains(new Vector3(i,l,-0.2f)) == false){
// g = Instantiate(Floor1, new Vector3(i,l,-0.2f), new Quaternion(0,0,0,0));
// Debug.Log(i + " " + l + " " + g.transform.position);
// n = false;
// }
// else if (n == false){
// g = Instantiate(Floor2, new Vector3(i,l,-0.2f), new Quaternion(0,0,0,0));
// n = true;
// }
}
}
}
}
I'm sorry if my title isn't right, if it is, please tell me some suggestions to change it to
,thanks
Goal:
to create a vehicle with properties similar to that of Mario Kart 8's anti gravity mode, or f- zero; the ability to ride on extreme non horizontal surfaces.
Desired behavior:
the vehicle should not turn unless the thumbstick or arrow keys are pressed/moved; it must keep a straight line of motion with the exception of roll and vertical curvature relative to the camera's view.
Actual behavior:
The vehicle will slowly(sometimes quickly) fall out of line and keep curving until the track stops bending. if placed in an inward facing cylinder and driven around radially, the vehicle will begin to curve towards either global +z or global +y.
(no error messages)
What I've tried:
-setting transform.up to the surface normal then rotating around the normal as an axis
-using quaternion.euler(0, [desired angle], 0) then fromToRotation
The alignment and rotation code:
transform.rotation = Quaternion.Euler(0, rotation, 0);
Quaternion tilt = Quaternion.FromToRotation(Vector3.up, localUp);
transform.rotation = tilt * transform.rotation;
transform.position += velocity * 1.1f;
The entire script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using PhysicsExtensions;
using UnityEngine.Rendering.PostProcessing;
public class Cart : MonoBehaviour
{
Kartphysics inputActions;
public new Transform camera, camTarget, camTargetDrift, Visual;
public ShipType shipType;
public AudioSource Vroom;
public Vector3 localUp = Vector3.up;
Vector3 velocity, camUp, followPos;
public AnimationCurve SteeringControl;
public float steerAmount;
float rotation, rollTarget, roll, fovDifference, vroomPitch = 0, flameLength = 0;
public float normalFov, speedFov, Velocity, rollAmount, speedFactor, forcedAcceleration;
public GameObject[] ships;
public FlamingTrail[] flames;
public PostProcessProfile ppp;
Vector2 JoystickVal;
ChromaticAberration ca;
LensDistortion ld;
Vector3 LastForward;
private void Start()
{
switch (shipType)
{
case ShipType.Carrier:
{
ships[0].SetActive(true);
break;
}
case ShipType.Ram:
{
ships[1].SetActive(true);
break;
}
}
ca = ppp.GetSetting<ChromaticAberration>();
ld = ppp.GetSetting<LensDistortion>();
}
private void Update()
{
UpdateVisuals();
UpdateCamera();
Velocity = velocity.magnitude;
}
private void FixedUpdate()
{
UpdateKart();
}
void SetFlames(float length)
{
for(int i = 0; i < flames.Length; i++)
{
flames[i].length = length;
}
}
void UpdateVisuals()
{
ca.intensity.value = Mathf.Clamp01(forcedAcceleration) * 2;
ld.intensity.value = Mathf.Lerp(0, -70f, Mathf.Clamp(forcedAcceleration, 0, 1));
SetFlames(flameLength);
Vroom.pitch = Mathf.Lerp(Vroom.pitch, vroomPitch, (speedFactor * 0.01f) * 10);
Visual.position = Vector3.Lerp(Visual.position, transform.position, (speedFactor * 0.01f) * 30);
Visual.rotation = Quaternion.Lerp(Visual.rotation, transform.rotation, (speedFactor * 0.01f) * 15);
}
void UpdateCamera()
{
fovDifference = speedFov - normalFov;
Camera.main.fieldOfView = speedFov - (fovDifference * (1 / Mathf.Clamp(velocity.magnitude + 1, 0, Mathf.Infinity)));
camUp = Vector3.Lerp(camUp, localUp.normalized, (speedFactor * 0.01f) * (Vector3.Distance(camera.position, Vector3.Lerp(camTarget.position, camTargetDrift.position, transform.InverseTransformDirection(velocity).x)) + 3));
camera.rotation = Quaternion.Slerp(camera.rotation, Quaternion.LookRotation((transform.position - (transform.right * transform.InverseTransformDirection(velocity).x * 5) + transform.up) - camera.position, camUp), (speedFactor * 0.01f) * 13);
camera.position = Vector3.Lerp(camera.position, Vector3.Lerp(camTarget.position, camTargetDrift.position, transform.InverseTransformDirection(velocity).x), (speedFactor * 0.01f) * Vector3.Distance(camera.position, camTarget.position) * 20);
}
void UpdateKart()
{
JoystickVal = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
if (Input.GetAxis("Submit") > 0.5)
JoystickVal = new Vector2(JoystickVal.x, 1);
if (Input.GetAxis("Cancel") > 0.5)
JoystickVal = new Vector2(JoystickVal.x, -1);
if (JoystickVal.magnitude > 1)
{
JoystickVal.Normalize();
}
JoystickVal *= (speedFactor * 0.01f) * 0.2f;
JoystickVal /= Mathf.Clamp(velocity.magnitude, 0.7f, Mathf.Infinity);
velocity += ((transform.forward * JoystickVal.y) / Mathf.Clamp(Mathf.Abs(transform.InverseTransformDirection(velocity).x), 0.7f, Mathf.Infinity));
rollTarget = Mathf.Clamp01(SteeringControl.Evaluate(velocity.magnitude)) * JoystickVal.x * rollAmount;
roll = Mathf.MoveTowards(roll, rollTarget, (speedFactor * 0.01f) * 4);
velocity -= localUp * (speedFactor * 0.01f) * 0.7f;
velocity /= 1 + ((speedFactor * 0.01f) / 8);
RaycastHit hit;
CircleCastHit circleHit;
if (Physics.Raycast(transform.position + transform.up, -transform.up + (velocity / 1), out hit))
{
if (hit.distance < 4)
{
transform.position -= hit.normal.normalized * (speedFactor * 0.01f);
localUp = Vector3.MoveTowards(localUp, hit.normal, (speedFactor * 0.01f) * 9);
if (hit.distance < 1.2f)
{
flameLength = Velocity * 2;
if (hit.collider.tag == "SpeedPanel")
forcedAcceleration = 3f;
rotation += SteeringControl.Evaluate(velocity.magnitude * 0.7f) * JoystickVal.x * (speedFactor * 0.01f) * 100 * steerAmount;
transform.position += hit.normal.normalized * (1 - hit.distance);
vroomPitch = velocity.magnitude * 1.5f;
velocity += ((transform.forward * ((JoystickVal.y * 1.3f) + (forcedAcceleration / 100))) / Mathf.Clamp(Mathf.Abs(transform.InverseTransformDirection(velocity).x), 0.7f, Mathf.Infinity));
rotation += SteeringControl.Evaluate((speedFactor * 0.01f) * velocity.magnitude * 50) * JoystickVal.x * 0.3f;
velocity /= 1 + ((speedFactor * 0.01f));
velocity -= transform.right * transform.InverseTransformDirection(velocity).x * 0.2f;
Vector3 force = (hit.normal * -transform.InverseTransformDirection(velocity).y / Mathf.Clamp(hit.distance - 0.1f, 0.5f, 2)) * 1.1f;
if (force.magnitude > 1)
force = force.normalized * 1;
force /= 8;
velocity += force;
}
else
{
vroomPitch = 0;
flameLength = Mathf.MoveTowards(flameLength, 0, 0.03f);
}
}
else
{
localUp = Vector3.MoveTowards(localUp, Vector3.up, (speedFactor * 0.01f) * 1.2f);
vroomPitch = 0;
transform.forward = velocity.normalized;
flameLength = Mathf.MoveTowards(flameLength, 0, 0.03f);
}
}
else
{
localUp = Vector3.MoveTowards(localUp, Vector3.up, (speedFactor * 0.01f) * 2);
vroomPitch = 0;
flameLength = Mathf.MoveTowards(flameLength, 0, 0.03f);
}
if (PhysicsII.CircleCast(transform.position + (transform.up * 0.5f), localUp, 0.7f, 8, out circleHit))
{
Debug.DrawRay(circleHit.nearestHit().point, circleHit.nearestHit().normal, Color.red, 0.1f);
Debug.Log("HIT");
velocity += (transform.position + (transform.up * 0.5f) - circleHit.nearestHit().point) / 3;
if (circleHit.nearestHit().distance < 0.4f)
velocity += (transform.position + (transform.up * 0.5f) - circleHit.nearestHit().point) / 7;
if (circleHit.nearestHit().distance < 0.14f)
velocity += (transform.position + (transform.up * 0.5f) - circleHit.nearestHit().point) / 7;
}
if(Physics.Raycast(transform.position + (transform.up * 0.8f) - velocity, velocity , out hit))
{
if(hit.distance < Velocity * 2)
velocity /= 1 + ((speedFactor * 0.01f) * 2f);
if (hit.distance < Velocity * 1.2f)
velocity = Vector3.Reflect(velocity, hit.normal);
}
forcedAcceleration = Mathf.MoveTowards(forcedAcceleration, 0, 0.1f);
transform.rotation = Quaternion.Euler(0, rotation, 0);
Quaternion tilt = Quaternion.FromToRotation(Vector3.up, localUp);
transform.rotation = tilt * transform.rotation;
transform.position += velocity * 1.1f;
}
public enum ShipType
{
Carrier = 0,
Ram = 1
}
}
Here's a partial answer because I can't test it on my end currently to see if it works. It also appears like "roll" isn't yet used for anything (is it meant to alter the local up of the transform somehow?) so I'm not sure about that.
First, instead of keeping a float rotation to keep track of how the vehicle is turned, you can just use transform.forward or transform.right for those purposes, and measure the modifications to that on a per-frame basis:
void UpdateKart()
{
Vector3 newForward = transform.forward;
float turnAmount = 0f;
// ...
if (hit.distance < 1.2f)
{
flameLength = Velocity * 2;
if (hit.collider.tag == "SpeedPanel")
forcedAcceleration = 3f;
turnAmount += SteeringControl.Evaluate(velocity.magnitude * 0.7f)
* JoystickVal.x * (speedFactor * 0.01f) * 100 * steerAmount;
transform.position += hit.normal.normalized * (1 - hit.distance);
vroomPitch = velocity.magnitude * 1.5f;
velocity += /* too long to bother formatting */
turnAmount += SteeringControl.Evaluate((speedFactor * 0.01f)
* velocity.magnitude * 50) * JoystickVal.x * 0.3f;
// ...
Then when you actually adjust the rotation, apply the turn amount around the local up axis to the current local forward direction. And finally, set the transform's rotation so that its new local up is localUp and it keeps its local forward as constant a direction as possible (cross products followed by Quaternion.LookRotation can be used for this):
forcedAcceleration = Mathf.MoveTowards(forcedAcceleration, 0, 0.1f);
Vector3 turnedForward = Quaternion.AngleAxis(turnAmount - 180, localUp) *
transform.forward;
Vector3 newRight = Vector3.Cross(turnedForward, localUp);
if (newRight == Vector3.zero)
{
/* Ambiguous situation - maybe kart landed with its nose directly in the
direction of localUp or opposite direction. Possible solution: use
velocity as previous forward direction and recalculate, using a random
direction if that doesn't work
*/
newRight = Vector3.Cross(velocity, localUp);
if (newRight == Vector3.zero)
{
newRight = Vector3.ProjectOnPlane(Random.insideUnitSphere,
localUp).normalized;
}
}
Vector3 newForward = Vector3.Cross(newRight, localUp);
transform.rotation = Quaternion.LookRotation(newForward, localUp);
transform.position += velocity * 1.1f;
The reason you're seeing the results you are is that FromToRotation will give you the "smallest" rotation that will move one vector to the other. But you're more concerned with a rotation that will keep the local forward close to what they are before the adjustment (it's difficult to explain why this isn't the same thing). Hence the Cross stuff.
As I said, this is only intended to be a partial solution to get you closer. But, it may be all you need. Let me know what you think in the comments.
I have a gameobject and position and rotation are set originally as
mainModel.transform.position = new Vector3 (-3.25f,-0.2f,0.1f);
mainModel.transform.rotation = Quaternion.Euler (0,95,0);
Then I spin the model in swiping as
f_difX = Mathf.Abs(f_lastX - Input.GetAxis ("Mouse X"));
if (f_lastX < Input.GetAxis ("Mouse X"))
{
i_direction = -1;
if (yPos > (Screen.height*3 / 4)) {
Swinginfo.SetActive (true);
Swinginfo2.SetActive (false);
} else if(yPos < (Screen.height*3 / 4) && yPos > (Screen.height / 4)){
m_CurrentObj.transform.Rotate(Vector3.up, -f_difX);
}
}
if (f_lastX > Input.GetAxis ("Mouse X"))
{
i_direction = 1;
if (yPos > (Screen.height*3 / 4)) {
Swinginfo.SetActive (false);
Swinginfo2.SetActive (true);
} else if(yPos < (Screen.height*3 / 4) && yPos > (Screen.height / 4)){
m_CurrentObj.transform.Rotate(Vector3.up, f_difX);
}
}
f_lastX = -Input.GetAxis ("Mouse X")*1.5f;
The model spin.
When I want to set its initial position and rotation, I set as
mainModel.transform.position = new Vector3 (-3.25f,-0.2f,0.1f);
mainModel.transform.rotation = Quaternion.Euler (0,95,0);
But it doesn't change back to its initial setting.
How can I have its initial position and rotation?
EDIT:
Debug.Log ("RangeViewScript.index "+RangeViewScript.index);
if (RangeViewScript.index == 0) {//pass
mainModel.transform.position = new Vector3 (-3.25f,-0.2f,0);
mainModel.transform.rotation = Quaternion.Euler (0,95,0);
Debug.Log ("Reset 0 is called");
}else if (RangeViewScript.index == 1) {//cheapshot
mainModel.transform.position = new Vector3 (-2.6f,-0.2f,0);
mainModel.transform.rotation = Quaternion.Euler (0,105,0);
Debug.Log ("Reset 1 is called");
}else if (RangeViewScript.index == 2) {//fullswing driver
mainModel.transform.position = new Vector3 (-5.0f,-0.2f,0);
mainModel.transform.rotation = Quaternion.Euler (0,90,0);
Debug.Log ("Reset 2 is called");
}else if (RangeViewScript.index == 3) {//putting
mainModel.transform.position = new Vector3 (-1.9f,-0.2f,0.1f);
mainModel.transform.rotation = Quaternion.Euler (0,95,0);
Debug.Log ("Reset 3 is called");
}else if (RangeViewScript.index == 4) {//shoot
mainModel.transform.position = new Vector3 (-2.75f,-0.2f,0.69f);
mainModel.transform.rotation = Quaternion.Euler (0,100,0);
Debug.Log ("Reset 4 is called");
}else if (RangeViewScript.index == 5) {//shoot
mainModel.transform.position = new Vector3 (-3.25f,-0.2f,0.1f);
mainModel.transform.rotation = Quaternion.Euler (0,95,0);
Debug.Log ("Reset 5 is called");
}
I made the precursor to my 3d Agario game. It is a mouse-oriented game. You use the mouse to control most of the movement. This includes the rotation of the Camera.
My problem is the Camera won't stop rotating. This is because it is very hard to center the mouse to the center of the screen, and the way I made the Camera rotate is by using a Sine equation.
Here is my code:
//public
public GameObject player;
public float rotationSpeed;
//v3
private Vector3 mousePos;
private Vector3 playerPos;
private Vector3 camPos;
//float
private float sideX;
private float sideZ;
private float sideC;
private float camX;
private float camZ;
private float camC;
private float rotX;
private float rotZ;
private float rotC;
private float rotAngle;
private Quaternion currRotation;
//camera
private Camera hitCam;
void Start ()
{
transform.rotation = Quaternion.Euler(30, 0, 0);
transform.position = new Vector3(0, 15, 0);
}
void LateUpdate ()
{
mousePos = HitCameraController.mousePos;
playerPos = player.transform.position;
sideX = (mousePos.x - playerPos.x);
sideZ = (mousePos.z - playerPos.z);
sideC = (Mathf.Sqrt(Mathf.Pow(sideX, 2) + Mathf.Pow(sideZ, 2)));
camC = 15;
camX = (camC * sideX) / sideC;
camZ = (camC * sideZ) / sideC;
rotX = (sideX + camX);
rotZ = (sideZ + camZ);
rotC = (Mathf.Sqrt(Mathf.Pow(rotX, 2) + Mathf.Pow(rotZ, 2)));
if (rotX >= 0 && rotZ >= 0)
{
rotAngle = (Mathf.Asin(rotX / rotC) * Mathf.Rad2Deg);
}
if (rotX >= 0 && rotZ <= 0)
{
rotAngle = 180 - (Mathf.Asin(rotX / rotC) * Mathf.Rad2Deg);
}
if (rotX <= 0 && rotZ >= 0)
{
rotAngle = (Mathf.Asin(rotX / rotC) * Mathf.Rad2Deg);
}
if (rotX <= 0 && rotZ <= 0)
{
rotAngle = -180 - (Mathf.Asin(rotX / rotC) * Mathf.Rad2Deg);
}
camPos = new Vector3((playerPos.x - camX), 15, (playerPos.z - camZ));
currRotation = Quaternion.Euler(30, rotAngle, 0);
// Move Camera
transform.position = camPos;
// Rotate Camera
/*transform.rotation = Quaternion.RotateTowards(
transform.rotation, currRotation,
(rotationSpeed * Time.deltaTime));*/
transform.rotation = currRotation;
}
I want to make a sort of "safe-zone" that will prevent the calculation of the rotating angle. For instance, if I keep my mouse within a certain boundary in the center, the Camera won't rotate.
I tried to make the boundary using an "or" statement, but it didn't give me the result I was looking for (the camera would still rotate even when my mouse was in the boundary. The Camera would stop on some tries, but it would jitter immensely before doing so.)
I know exactly why this is occurring: the ray isn't being cast on a still camera; hence, the mouse coordinate will always change, even if I don't move the mouse. I tried casting the ray to the "Hit" camera (the still Camera), but the follow camera couldn't pick up on the mouse movement. I don't know how to fix this problem other than to keep brainstorming for an intuitive solution, but my brain can only innovate so much.
If you could think of a solution before me, let me know by any means.
[...]
void LateUpdate ()
{
mousePos = HitCameraController.mousePos;
playerPos = player.transform.position;
sideX = (mousePos.x - playerPos.x);
sideZ = (mousePos.z - playerPos.z);
sideC = (Mathf.Sqrt(Mathf.Pow(sideX, 2) + Mathf.Pow(sideZ, 2)));
// New Stuff
sideC -= 5f; // substract the safe-zone-radius
if(sideC < 0f)
{
// Inside safe-zone, do nothing.
sideC = 0f;
sideX = 0f;
sideZ = 0f;
}else{
// Outside safe-zone, correct values to avoid jumping.
float x_ratio = sideX / sideZ; // be careful with "divide by zero"
float z_ratio = sideZ / sideX;
sideX -= 5 * x_ratio;
sideZ -= 5 * z_ratio;
}
// End New Stuff
camC = 15;
camX = (camC * sideX) / sideC;
camZ = (camC * sideZ) / sideC;
rotX = (sideX + camX);
rotZ = (sideZ + camZ);
rotC = (Mathf.Sqrt(Mathf.Pow(rotX, 2) + Mathf.Pow(rotZ, 2)));
if (rotX >= 0 && rotZ >= 0)
{
rotAngle = (Mathf.Asin(rotX / rotC) * Mathf.Rad2Deg);
}
if (rotX >= 0 && rotZ <= 0)
{
rotAngle = 180 - (Mathf.Asin(rotX / rotC) * Mathf.Rad2Deg);
}
if (rotX <= 0 && rotZ >= 0)
{
rotAngle = (Mathf.Asin(rotX / rotC) * Mathf.Rad2Deg);
}
if (rotX <= 0 && rotZ <= 0)
{
rotAngle = -180 - (Mathf.Asin(rotX / rotC) * Mathf.Rad2Deg);
}
camPos = new Vector3((playerPos.x - camX), 15, (playerPos.z - camZ));
currRotation = Quaternion.Euler(30, rotAngle, 0);
I wrote a script for the player movement in c#. Whenever the player presses A or D, it moves him/her to the left or right by 12 units and when the player presses W or S, it moves him/her up or down by 12 units. My script works fine, but if a person starts to spam all of the keys at once, it glitches out and the player object is not in line with the level anymore. I want to have the script check if there a movement is currently happening before executing the movement on the keypress. Here is my script:
void Update () {
transform.Translate(Vector3.forward * ForwardSpeed * Time.deltaTime);
if (Input.GetKeyDown (KeyCode.A) && side > maxSideLeft) {
MoveObjectTo(this.transform, new Vector3(this.transform.position.x - 12, this.transform.position.y, this.transform.position.z + 10), movementSpeed);
side -= 1;
} else if (Input.GetKeyDown (KeyCode.D) && side < maxSideRight) {
MoveObjectTo(this.transform, new Vector3(this.transform.position.x + 12, this.transform.position.y, this.transform.position.z + 10), movementSpeed);
side += 1;
}
if (Input.GetKeyDown (KeyCode.W) && level < maxLevelHeight) {
MoveObjectTo(this.transform, new Vector3(this.transform.position.x, this.transform.position.y + 12, this.transform.position.z + 10), movementSpeed);
level += 1;
} else if (Input.GetKeyDown (KeyCode.S) && level > minLevelHeight) {
MoveObjectTo(this.transform, new Vector3(this.transform.position.x, this.transform.position.y - 12, this.transform.position.z + 10), movementSpeed);
level -= 1;
}
if (Input.GetKeyDown (KeyCode.R) || Input.GetKeyDown(KeyCode.Space)) {
SceneManager.LoadScene ("Scene1");
Time.timeScale = 1;
}
}
private void MoveObjectTo(Transform objectToMove, Vector3 targetPosition, float moveSpeed)
{
StopCoroutine(MoveObject(objectToMove, targetPosition, moveSpeed));
StartCoroutine(MoveObject(objectToMove, targetPosition, moveSpeed));
}
public static IEnumerator MoveObject(Transform objectToMove, Vector3 targetPosition, float moveSpeed)
{
float currentProgress = 0;
Vector3 cashedObjectPosition = objectToMove.transform.position;
while (currentProgress <= 1)
{
currentProgress += moveSpeed * Time.deltaTime;
objectToMove.position = Vector3.Lerp(cashedObjectPosition, targetPosition, currentProgress);
yield return null;
}
}
You can use a simple isMoving variable for this. Don't move if the variable is true. Move if it is false. When the coroutine is done running set isMoving back to false. Also, I can't tell why MoveObject function is static. I removed the static keyword from it.
bool isMoving = false;
void Update()
{
transform.Translate(Vector3.forward * ForwardSpeed * Time.deltaTime);
if (Input.GetKeyDown(KeyCode.A) && side > maxSideLeft)
{
MoveObjectTo(this.transform, new Vector3(this.transform.position.x - 12, this.transform.position.y, this.transform.position.z + 10), movementSpeed);
side -= 1;
}
else if (Input.GetKeyDown(KeyCode.D) && side < maxSideRight)
{
MoveObjectTo(this.transform, new Vector3(this.transform.position.x + 12, this.transform.position.y, this.transform.position.z + 10), movementSpeed);
side += 1;
}
if (Input.GetKeyDown(KeyCode.W) && level < maxLevelHeight)
{
MoveObjectTo(this.transform, new Vector3(this.transform.position.x, this.transform.position.y + 12, this.transform.position.z + 10), movementSpeed);
level += 1;
}
else if (Input.GetKeyDown(KeyCode.S) && level > minLevelHeight)
{
MoveObjectTo(this.transform, new Vector3(this.transform.position.x, this.transform.position.y - 12, this.transform.position.z + 10), movementSpeed);
level -= 1;
}
if (Input.GetKeyDown(KeyCode.R) || Input.GetKeyDown(KeyCode.Space))
{
SceneManager.LoadScene("Scene1");
Time.timeScale = 1;
}
}
private void MoveObjectTo(Transform objectToMove, Vector3 targetPosition, float moveSpeed)
{
//Don't do anything Object is already moving
if (isMoving)
{
return;
}
//If not moving set isMoving to true
isMoving = true;
StartCoroutine(MoveObject(objectToMove, targetPosition, moveSpeed));
}
public IEnumerator MoveObject(Transform objectToMove, Vector3 targetPosition, float moveSpeed)
{
float currentProgress = 0;
Vector3 cashedObjectPosition = objectToMove.transform.position;
while (currentProgress <= 1)
{
currentProgress += moveSpeed * Time.deltaTime;
objectToMove.position = Vector3.Lerp(cashedObjectPosition, targetPosition, currentProgress);
yield return null;
}
//Done moving. Set isMoving to false
isMoving = false;
}
It sounds like you want to check to see if the user has completed their lerp before lerping to some new position. In that case, you will want to prevent your player from moving again until your currentProgress variable is equal to 1. Thus, use a simple boolean callback and prevent calling the Corouting until that callback is true. Your MoveObject function:
public static IEnumerator MoveObject(Transform objectToMove, Vector3 targetPosition, float moveSpeed, System.Action<bool> callBack)
{
float currentProgress = 0;
Vector3 cashedObjectPosition = objectToMove.transform.position;
while (currentProgress <= 1)
{
currentProgress += moveSpeed * Time.deltaTime;
objectToMove.position = Vector3.Lerp(cashedObjectPosition, targetPosition, currentProgress);
yield return null;
if (currentProgress >= 1)
callBack(true);
}
}
Then you can change your MoveObjectTo function to read this callback:
private void MoveObjectTo(Transform objectToMove, Vector3 targetPosition, float moveSpeed)
{
if (canCallCoroutine)
{
canCallCoroutine = false;
StartCoroutine(MoveObject(objectToMove, targetPosition, moveSpeed, finished =>
{
if (finished != null)
{
if (finished)
canCallCoroutine = true;
}
}));
}
}