I am looking for following implementation in unity based touch game:
I need object to rotate with the touch so it can be viewed from all sides(As long as touch is moving)
The object should keep on rotating in direction of previous touch
movement (when touch ends)
I tried implementing below code. But rotation is quiet quirky. It sometime rotates too fast sometimes in opposite direction of the swipe etc.
Here is what i have tried:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Functionalities : MonoBehaviour
{
public GameObject m_objecttorotate;
Vector3 localAngle;
[SerializeField]
float rotateSpeed = 0.09f;
Touch touchZero;
Vector3 rotateAxis;
float newMouseYpos = 0;
float prevMouseYpos = 0;
bool isIncreasing;
bool isDecreasing;
bool rotateManually;
void Update()
{
if (Input.touchCount > 0)
{
touchZero = Input.GetTouch(0);
//Rotate the model based on offset
localAngle = m_objecttorotate.transform.localEulerAngles;
localAngle.y -= rotateSpeed * touchZero.deltaPosition.x;
m_objecttorotate.transform.localEulerAngles = localAngle;
if (touchZero.deltaPosition != Vector2.zero)
{
rotateAxis = touchZero.deltaPosition;
}
}
else
{
localAngle.y += rotateSpeed * rotateAxis.y;
m_objecttorotate.transform.localEulerAngles = localAngle;
}
CheckIfTouchIsMovingUpOrDown();
if (isIncreasing)
{
Vector3 newPos = new Vector3(m_objecttorotate.transform.position.x, -0.25f, m_objecttorotate.transform.position.z);
m_objecttorotate.transform.position = Vector3.Lerp(m_objecttorotate.transform.position, newPos, 1 * Time.deltaTime);
}
else if (isDecreasing)
{
Vector3 newPos = new Vector3(m_objecttorotate.transform.position.x, 0.25f, m_objecttorotate.transform.position.z);
m_objecttorotate.transform.position = Vector3.Lerp(m_objecttorotate.transform.position, newPos, 1 * Time.deltaTime);
}
else
{
Vector3 newPos = new Vector3(m_objecttorotate.transform.position.x, 0f, m_objecttorotate.transform.position.z);
m_objecttorotate.transform.position = Vector3.Lerp(m_objecttorotate.transform.position, newPos, 1 * Time.deltaTime);
}
}
void CheckIfTouchIsMovingUpOrDown()
{
if (Input.GetMouseButton(0))
{
if (prevMouseYpos != newMouseYpos)
{
if (prevMouseYpos < newMouseYpos + 1f)
{
isIncreasing = true;
isDecreasing = false;
Debug.Log("Increasing");
prevMouseYpos = newMouseYpos;
}
else if (prevMouseYpos > newMouseYpos - 1f)
{
isDecreasing = true;
isIncreasing = false;
Debug.Log("Decreasing");
prevMouseYpos = newMouseYpos;
}
}
newMouseYpos = Input.mousePosition.y;
}
else
{
//isDecreasing = false;
// isIncreasing = false;
prevMouseYpos = newMouseYpos;
}
}
}
Related
I have object that move around in fixed radius around another object with random height.
In this script i want the transform(turret) to rotate facing the target(target is the object that move with the random height) and that the laser that shoot will hit all the time the moving around target.
In the original i used the mouse to rotate the transform to be facing objects but now i want that the transform will rotate automatic to the moving target with the laser.
I added this part to the script and the laser start when running the game but the transform is not rotating facing the target. and i still can rotate the transform with the mouse and in this case i don't want the mouse to rotate the transform but that the transform will be rotating automatic.
if (startLaser)
{
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
startLaser = false;
}
if (Cam != null)
{
RaycastHit hit;
RayMouse = Cam.ScreenPointToRay(target.position);
if(Physics.Raycast(RayMouse.origin, RayMouse.direction, out hit, MaxLength))
{
RotateToMouseDirection(gameObject, hit.point);
}
else
{
var pos = RayMouse.GetPoint(MaxLength);
RotateToMouseDirection(gameObject, pos);
}
}
but it's not working the transform is not rotating automatic and the mouse still controlling the rotating.
This is the full script :
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System;
using UnityEngine;
public class Hovl_DemoLasers : MonoBehaviour
{
public Transform target;
public GameObject FirePoint;
public Camera Cam;
public float MaxLength;
public GameObject[] Prefabs;
private Ray RayMouse;
private Vector3 direction;
private Quaternion rotation;
[Header("GUI")]
private float windowDpi;
private int Prefab;
private GameObject Instance;
private Hovl_Laser LaserScript;
private Hovl_Laser2 LaserScript2;
private bool rotateMouse = true;
private bool startLaser = true;
//Double-click protection
private float buttonSaver = 0f;
void Start ()
{
if (Screen.dpi < 1) windowDpi = 1;
if (Screen.dpi < 200) windowDpi = 1;
else windowDpi = Screen.dpi / 200f;
Counter(0);
}
void Update()
{
//Enable lazer
if (Input.GetMouseButtonDown(0))
{
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
rotateMouse = true;
}
if (Input.GetMouseButtonDown(1))
{
rotateMouse = false;
}
//To change lazers
if ((Input.GetKey(KeyCode.A) || Input.GetAxis("Horizontal") < 0) && buttonSaver >= 0.4f)// left button
{
buttonSaver = 0f;
Counter(-1);
}
if ((Input.GetKey(KeyCode.D) || Input.GetAxis("Horizontal") > 0) && buttonSaver >= 0.4f)// right button
{
buttonSaver = 0f;
Counter(+1);
}
buttonSaver += Time.deltaTime;
if (startLaser)
{
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
startLaser = false;
}
if (Cam != null)
{
RaycastHit hit;
RayMouse = Cam.ScreenPointToRay(target.position);
if(Physics.Raycast(RayMouse.origin, RayMouse.direction, out hit, MaxLength))
{
RotateToMouseDirection(gameObject, hit.point);
}
else
{
var pos = RayMouse.GetPoint(MaxLength);
RotateToMouseDirection(gameObject, pos);
}
}
//Current fire point
if (Cam != null && rotateMouse)
{
RaycastHit hit;
var mousePos = Input.mousePosition;
RayMouse = Cam.ScreenPointToRay(mousePos);
if (Physics.Raycast(RayMouse.origin, RayMouse.direction, out hit, MaxLength))
{
RotateToMouseDirection(gameObject, hit.point);
}
else
{
var pos = RayMouse.GetPoint(MaxLength);
RotateToMouseDirection(gameObject, pos);
}
}
else
{
Debug.Log("No camera");
}
}
//GUI Text
void OnGUI()
{
GUI.Label(new Rect(10 * windowDpi, 5 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use the keyboard buttons A/<- and D/-> to change lazers!");
GUI.Label(new Rect(10 * windowDpi, 20 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use left mouse button for shooting!");
}
//To change prefabs (count - prefab number)
void Counter(int count)
{
Prefab += count;
if (Prefab > Prefabs.Length - 1)
{
Prefab = 0;
}
else if (Prefab < 0)
{
Prefab = Prefabs.Length - 1;
}
}
//To rotate fire point
void RotateToMouseDirection (GameObject obj, Vector3 destination)
{
direction = destination - obj.transform.position;
rotation = Quaternion.LookRotation(direction);
obj.transform.localRotation = Quaternion.Lerp(obj.transform.rotation, rotation, 1);
}
}
This is working fine : I'm not sure if i need to use the out hit variable in the Automatic aiming part ? do i need to use the hit variable and if so how ?
// Automatic aiming part
if (Cam != null)
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, MaxLength))
{
RotateToMouseDirection(gameObject, target.position);
}
}
Anyway it's not working as i wanted.
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System;
using UnityEngine;
public class Hovl_DemoLasers : MonoBehaviour
{
public Transform target;
public GameObject FirePoint;
public Camera Cam;
public float MaxLength;
public GameObject[] Prefabs;
private Ray RayMouse;
private Ray AutomaticRay;
private Vector3 direction;
private Quaternion rotation;
[Header("GUI")]
private float windowDpi;
private int Prefab;
private GameObject Instance;
private Hovl_Laser LaserScript;
private Hovl_Laser2 LaserScript2;
private bool rotateMouse = true;
private bool startLaser = true;
//Double-click protection
private float buttonSaver = 0f;
void Start ()
{
//LaserEndPoint = new Vector3(0, 0, 0);
if (Screen.dpi < 1) windowDpi = 1;
if (Screen.dpi < 200) windowDpi = 1;
else windowDpi = Screen.dpi / 200f;
Counter(0);
}
void Update()
{
//Enable lazer
if (Input.GetMouseButtonDown(0))
{
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
rotateMouse = true;
}
if (Input.GetMouseButtonDown(1))
{
rotateMouse = false;
}
//Disable lazer prefab
if (Input.GetMouseButtonUp(0))
{
/*if (LaserScript) LaserScript.DisablePrepare();
if (LaserScript2) LaserScript2.DisablePrepare();
Destroy(Instance,1);*/
}
//To change lazers
if ((Input.GetKey(KeyCode.A) || Input.GetAxis("Horizontal") < 0) && buttonSaver >= 0.4f)// left button
{
buttonSaver = 0f;
Counter(-1);
}
if ((Input.GetKey(KeyCode.D) || Input.GetAxis("Horizontal") > 0) && buttonSaver >= 0.4f)// right button
{
buttonSaver = 0f;
Counter(+1);
}
buttonSaver += Time.deltaTime;
if (startLaser)
{
rotateMouse = false;
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
startLaser = false;
}
// Automatic aiming part
if (Cam != null)
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, MaxLength))
{
RotateToMouseDirection(gameObject, target.position);
}
}
//Current fire point
if (Cam != null && rotateMouse)
{
RaycastHit hit; //DELATE THIS IF YOU WANT TO USE LASERS IN 2D
var mousePos = Input.mousePosition;
RayMouse = Cam.ScreenPointToRay(mousePos);
//ADD THIS IF YOU WANT TO USE LASERS IN 2D: RaycastHit2D hit = Physics2D.Raycast(RayMouse.origin, RayMouse.direction, MaxLength);
if (Physics.Raycast(RayMouse.origin, RayMouse.direction, out hit, MaxLength)) //CHANGE THIS IF YOU WANT TO USE LASERRS IN 2D: if (hit.collider != null)
{
RotateToMouseDirection(gameObject, hit.point);
}
else
{
var pos = RayMouse.GetPoint(MaxLength);
RotateToMouseDirection(gameObject, pos);
}
}
else
{
Debug.Log("No camera");
}
}
//GUI Text
void OnGUI()
{
GUI.Label(new Rect(10 * windowDpi, 5 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use the keyboard buttons A/<- and D/-> to change lazers!");
GUI.Label(new Rect(10 * windowDpi, 20 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use left mouse button for shooting!");
}
//To change prefabs (count - prefab number)
void Counter(int count)
{
Prefab += count;
if (Prefab > Prefabs.Length - 1)
{
Prefab = 0;
}
else if (Prefab < 0)
{
Prefab = Prefabs.Length - 1;
}
}
//To rotate fire point
void RotateToMouseDirection (GameObject obj, Vector3 destination)
{
direction = destination - obj.transform.position;
rotation = Quaternion.LookRotation(direction);
obj.transform.localRotation = Quaternion.Lerp(obj.transform.rotation, rotation, 1);
}
}
I just need to add to it to make the character movement/camera stop moving when the UI is open for the quest, but I don't get where to put the code for the bool variable. And then put to write for the code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class QuestGiver : MonoBehaviour
{
public Quest quest;
public GameObject questWindow;
public Text titleText;
public Text descriptionText;
public Movement2 player;
public void OpenQuestWindow()
{
questWindow.SetActive(true);
titleText.text = quest.title;
descriptionText.text = quest.description;
}
public void AcceptQuest()
{
questWindow.SetActive(false);
quest.isActive = true;
player.quest = quest;
}
void Start()
{
questWindow = GameObject.Find("QuestWindow");
questWindow.SetActive(false);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement2 : MonoBehaviour
{
[SerializeField] CharacterController controller;
private Vector3 playerVelocity;
private bool groundedPlayer;
public float playerSpeed = 5.0f;
private float jumpHeight = 40f;
public float gravityValue = -9.81f;
public Transform Cam;
public KeyCode jump;
public KeyCode FlyUp;
public KeyCode FlyDown;
public bool ablefly;
private float FlyMax = 250f;
public Quest quest;
public int SoulHP = 30;
private void Start()
{
// add character controller
// controller = gameObject.AddComponent<CharacterController>();
}
void Update()
{
// check if the player is grounded and the vector3.y < 0, if one of this condition is true set back the playerVelocity.y = 0f;
groundedPlayer = controller.isGrounded;
if (groundedPlayer && playerVelocity.y < 0)
{
playerVelocity.y = 0f;
}
Vector3 flyup = new Vector3(0, 50, 0);
Vector3 flydown = new Vector3(0, -50, 0);
Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
// Look for the camera y Rotation and multiply it for the vector 3 move in order make the player direction y as same as the camera.
Vector3 FollowCam = Quaternion.Euler(0, Cam.eulerAngles.y, 0) * move;
controller.Move(FollowCam * Time.deltaTime * playerSpeed);
// makes the player jump by adding a float value to the vector 3 y
if (Input.GetKeyDown(jump) && ablefly == false && groundedPlayer == true)
{
playerVelocity.y += 4f;
//print("Diocane");
}
if (Input.GetKeyDown(FlyUp) && ablefly == true)
{
//flyup = Vector3.ClampMagnitude(flyup, 250f);
gravityValue = 0;
controller.Move(flyup * Time.deltaTime * playerSpeed);
}
if (Input.GetKeyDown(FlyDown) && ablefly == true)
{
//flyup = Vector3.ClampMagnitude(flyup, 250f);
gravityValue = 0;
controller.Move(flydown * Time.deltaTime * playerSpeed);
}
playerVelocity.y += gravityValue * Time.deltaTime;
controller.Move(playerVelocity * Time.deltaTime);
}
public void GoFind()
{
if (quest.isActive)
{
quest.goal.ItemCollected();
if (quest.goal.IsReached())
SoulHP += 30;
}
}
}
You could set the Time.timeScale to 0 when the ui is opened to make anything using deltaTime stop moving.
In the OpenQuestWindow() you would add Time.timeScale = 0;
and in the AcceptQuest() method add Time.timeScale = 1; to set it back to normal
This looks like a Similar question. please check this and ask me if you don't get that.
EDIT:
This is not a tested code, but I hope will give you an idea, of how to proceed.
1- define a public bool variable mybool in Movement2 script
2- call that bool in the QuestGiver Script like this:
void Start() {
questWindow = GameObject.Find("QuestWindow");
questWindow.SetActive(false);
player.mybool = false; // or get the player gameobject by tag...
}
update your Movement2 update function to this:
void Update() {
if (mybool) {
// check if the player is grounded and the vector3.y < 0, if one of this condition is true set back the playerVelocity.y = 0f;
groundedPlayer = controller.isGrounded;
if (groundedPlayer && playerVelocity.y < 0) {
playerVelocity.y = 0 f;
}
Vector3 flyup = new Vector3(0, 50, 0);
Vector3 flydown = new Vector3(0, -50, 0);
Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
// Look for the camera y Rotation and multiply it for the vector 3 move in order make the player direction y as same as the camera.
Vector3 FollowCam = Quaternion.Euler(0, Cam.eulerAngles.y, 0) * move;
controller.Move(FollowCam * Time.deltaTime * playerSpeed);
// makes the player jump by adding a float value to the vector 3 y
if (Input.GetKeyDown(jump) && ablefly == false && groundedPlayer == true) {
playerVelocity.y += 4 f;
//print("Diocane");
}
if (Input.GetKeyDown(FlyUp) && ablefly == true) {
//flyup = Vector3.ClampMagnitude(flyup, 250f);
gravityValue = 0;
controller.Move(flyup * Time.deltaTime * playerSpeed);
}
if (Input.GetKeyDown(FlyDown) && ablefly == true) {
//flyup = Vector3.ClampMagnitude(flyup, 250f);
gravityValue = 0;
controller.Move(flydown * Time.deltaTime * playerSpeed);
}
playerVelocity.y += gravityValue * Time.deltaTime;
controller.Move(playerVelocity * Time.deltaTime);
}
if (!camMove) {
Vector3 move = new Vector3(0, 0, 0);
}
}
Now update that bool in QuestGiver:
public void OpenQuestWindow()
{
questWindow.SetActive(true);
titleText.text = quest.title;
descriptionText.text = quest.description;
player.mybool = false;
}
public void AcceptQuest()
{
questWindow.SetActive(false);
quest.isActive = true;
player.quest = quest;
player.mybool = true;
}
I want to move the object up smooth slowly from it's current position on y 50.01 to new position 51.255
But the object keep moving up nonstop.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class RoboSphereWindowBreakInteraction : MonoBehaviour
{
public Transform target;
public AudioClip audioClip;
public float speed;
private bool hasStarted = false;
private Animator anim;
void Update()
{
if ((Input.GetKeyDown(KeyCode.B) || (hasStarted == true)))
{
float step = speed * Time.deltaTime; // calculate distance to move
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
hasStarted = true;
}
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.name == "Square 1")
{
GetComponent<Rigidbody>().isKinematic = false;
hasStarted = false;
Destroy(GameObject.Find("Wall_Window_Long_03"));
}
}
public void ActivateRoboSphere()
{
foreach(Transform child in transform)
{
if(child.name == "Camera")
{
RepositionCamera(child);
}
}
anim = GetComponent<Animator>();
anim.enabled = true;
GetComponent<FPEInteractableActivateScript>().interactionString = "";
FPEInteractionManagerScript.Instance.BeginCutscene();
StartCoroutine(PlayAudio());
}
private void RepositionCamera(Transform camera)
{
var Eyes = GameObject.Find("eyeDome");
camera.position = Eyes.transform.position + Eyes.transform.forward;
camera.LookAt(Eyes.transform);
camera.GetComponent<Camera>().enabled = true;
}
IEnumerator PlayAudio()
{
AudioSource audio = GetComponent<AudioSource>();
audio.clip = audioClip;
audio.Play();
yield return new WaitForSeconds(audio.clip.length);
var rotation = Quaternion.LookRotation(target.position - transform.position);
StartCoroutine(Spin(3f, rotation, () =>
{
anim.SetBool("Roll_Anim", true);
}));
StartCoroutine(MoveFromTo(transform, transform.position, new Vector3(transform.position.x,
transform.position.y + 51.255f, transform.position.z), 3f));
}
IEnumerator Spin(float lerpTime, Quaternion rotation, Action whenDone)
{
float elapsedTime = 0f;
while (elapsedTime <= lerpTime)
{
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, elapsedTime / lerpTime);
elapsedTime += Time.deltaTime;
yield return null;
}
whenDone?.Invoke();
}
// 51.255
IEnumerator MoveFromTo(Transform objectToMove, Vector3 a, Vector3 b, float speed)
{
float step = (speed / (a - b).magnitude) * Time.fixedDeltaTime;
float t = 0;
while (t <= 1.0f)
{
t += step; // Goes from 0 to 1, incrementing by step each time
objectToMove.position = Vector3.Lerp(a, b, t); // Move objectToMove closer to b
yield return new WaitForFixedUpdate(); // Leave the routine and return here in the next frame
}
objectToMove.position = b;
}
}
I did :
StartCoroutine(MoveFromTo(transform, transform.position, new Vector3(transform.position.x,
transform.position.y + 51.255f, transform.position.z), 3f));
But the object keep moving up nonstop. Or at least very high and not like I wanted from 50.01 to 51.255
And when the object reaching the height of 51.255 then I want it to move fast smooth forward to target.
In your code replace this part:
StartCoroutine(MoveFromTo(transform, transform.position, new Vector3(transform.position.x,
transform.position.y + 51.255f, transform.position.z), 3f));
with this:
StartCoroutine(MoveFromTo(transform, transform.position, new Vector3(transform.position.x,
51.255f, transform.position.z), 3f));
I have a ThirdPersonController in the Hierarchy.
Then i'm adding to it a Nav Mesh Agent.
The dragging to it the scrip in c#.
Then in the Inspector i'm adding in the script part the agent.
Then baking.
And it was working more or less with some stuttering but was working.
The character ThirdPersonController walked automatic to specific point in this case to a cylinder i have on my Terrain.
I can't figure out why first time/s it's working fine but then now i have this error.
This is the script i'm using for the automatic walk:
using System.Collections;
using UnityStandardAssets.Characters.ThirdPerson;
public class BasicAi : MonoBehaviour {
public NavMeshAgent agent;
public ThirdPersonCharacter character;
public enum State {
PATROL,
CHASE
}
public State state;
private bool alive;
// Variables for patrolling
public GameObject[] waypoints;
private int waypointInd = 0;
public float patrolSpeed = 0.5f;
// Variable for chasing
public float chaseSpeed = 1f;
public GameObject target;
// Use this for initialization
void Start () {
agent = GetComponent<NavMeshAgent> ();
character = GetComponent<ThirdPersonCharacter>();
agent.updatePosition = true;
agent.updateRotation = false;
state = BasicAi.State.PATROL;
alive = true;
StartCoroutine ("FSM");
}
IEnumerator FSM()
{
while (alive)
{
switch (state)
{
case State.PATROL:
Patrol ();
break;
case State.CHASE:
Chase ();
break;
}
yield return null;
}
}
void Patrol()
{
agent.speed = patrolSpeed;
if (Vector3.Distance (this.transform.position, waypoints [waypointInd].transform.position) >= 2) {
agent.SetDestination (waypoints [waypointInd].transform.position);
character.Move (agent.desiredVelocity, false, false);
} else if (Vector3.Distance (this.transform.position, waypoints [waypointInd].transform.position) <= 2) {
waypointInd += 1;
if (waypointInd > waypoints.Length) {
waypointInd = 0;
}
}
else
{
character.Move (Vector3.zero, false, false);
}
}
void Chase()
{
agent.speed = chaseSpeed;
agent.SetDestination (target.transform.position);
character.Move (agent.desiredVelocity, false, false);
}
void OnTriggerEnter(Collider coll)
{
if (coll.tag == "Player")
{
state = BasicAi.State.CHASE;
target = coll.gameObject;
}
}
// Update is called once per frame
void Update () {
}
And the exception error message is:
NullReferenceException: Object reference not set to an instance of an object
UnityStandardAssets.Characters.ThirdPerson.ThirdPersonCharacter.CheckGroundStatus () (at Assets/Standard Assets/Characters/ThirdPersonCharacter/Scripts/ThirdPersonCharacter.cs:215)
UnityStandardAssets.Characters.ThirdPerson.ThirdPersonCharacter.Move (Vector3 move, Boolean crouch, Boolean jump) (at Assets/Standard Assets/Characters/ThirdPersonCharacter/Scripts/ThirdPersonCharacter.cs:54)
BasicAi.Patrol () (at Assets/My Scripts/BasicAi.cs:72)
BasicAi+<FSM>c__Iterator0.MoveNext () (at Assets/My Scripts/BasicAi.cs:55)
UnityEngine.MonoBehaviour:StartCoroutine(String)
BasicAi:Start() (at Assets/My Scripts/BasicAi.cs:43)
When i click on the error message in the Console window it's going to the ThirdPersonCharacter script. The script is from in Unity.
The error is on the line:
m_Animator.applyRootMotion = true;
And this is the ThirdPersonCharacter script where the error is:
using UnityEngine;
namespace UnityStandardAssets.Characters.ThirdPerson
{
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(CapsuleCollider))]
[RequireComponent(typeof(Animator))]
public class ThirdPersonCharacter : MonoBehaviour
{
[SerializeField] float m_MovingTurnSpeed = 360;
[SerializeField] float m_StationaryTurnSpeed = 180;
[SerializeField] float m_JumpPower = 12f;
[Range(1f, 4f)][SerializeField] float m_GravityMultiplier = 2f;
[SerializeField] float m_RunCycleLegOffset = 0.2f; //specific to the character in sample assets, will need to be modified to work with others
[SerializeField] float m_MoveSpeedMultiplier = 1f;
[SerializeField] float m_AnimSpeedMultiplier = 1f;
[SerializeField] float m_GroundCheckDistance = 0.1f;
Rigidbody m_Rigidbody;
Animator m_Animator;
bool m_IsGrounded;
float m_OrigGroundCheckDistance;
const float k_Half = 0.5f;
float m_TurnAmount;
float m_ForwardAmount;
Vector3 m_GroundNormal;
float m_CapsuleHeight;
Vector3 m_CapsuleCenter;
CapsuleCollider m_Capsule;
bool m_Crouching;
void Start()
{
m_Animator = GetComponent<Animator>();
m_Rigidbody = GetComponent<Rigidbody>();
m_Capsule = GetComponent<CapsuleCollider>();
m_CapsuleHeight = m_Capsule.height;
m_CapsuleCenter = m_Capsule.center;
m_Rigidbody.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationY | RigidbodyConstraints.FreezeRotationZ;
m_OrigGroundCheckDistance = m_GroundCheckDistance;
}
public void Move(Vector3 move, bool crouch, bool jump)
{
// convert the world relative moveInput vector into a local-relative
// turn amount and forward amount required to head in the desired
// direction.
if (move.magnitude > 1f) move.Normalize();
move = transform.InverseTransformDirection(move);
CheckGroundStatus();
move = Vector3.ProjectOnPlane(move, m_GroundNormal);
m_TurnAmount = Mathf.Atan2(move.x, move.z);
m_ForwardAmount = move.z;
ApplyExtraTurnRotation();
// control and velocity handling is different when grounded and airborne:
if (m_IsGrounded)
{
HandleGroundedMovement(crouch, jump);
}
else
{
HandleAirborneMovement();
}
ScaleCapsuleForCrouching(crouch);
PreventStandingInLowHeadroom();
// send input and other state parameters to the animator
UpdateAnimator(move);
}
void ScaleCapsuleForCrouching(bool crouch)
{
if (m_IsGrounded && crouch)
{
if (m_Crouching) return;
m_Capsule.height = m_Capsule.height / 2f;
m_Capsule.center = m_Capsule.center / 2f;
m_Crouching = true;
}
else
{
Ray crouchRay = new Ray(m_Rigidbody.position + Vector3.up * m_Capsule.radius * k_Half, Vector3.up);
float crouchRayLength = m_CapsuleHeight - m_Capsule.radius * k_Half;
if (Physics.SphereCast(crouchRay, m_Capsule.radius * k_Half, crouchRayLength, Physics.AllLayers, QueryTriggerInteraction.Ignore))
{
m_Crouching = true;
return;
}
m_Capsule.height = m_CapsuleHeight;
m_Capsule.center = m_CapsuleCenter;
m_Crouching = false;
}
}
void PreventStandingInLowHeadroom()
{
// prevent standing up in crouch-only zones
if (!m_Crouching)
{
Ray crouchRay = new Ray(m_Rigidbody.position + Vector3.up * m_Capsule.radius * k_Half, Vector3.up);
float crouchRayLength = m_CapsuleHeight - m_Capsule.radius * k_Half;
if (Physics.SphereCast(crouchRay, m_Capsule.radius * k_Half, crouchRayLength, Physics.AllLayers, QueryTriggerInteraction.Ignore))
{
m_Crouching = true;
}
}
}
void UpdateAnimator(Vector3 move)
{
// update the animator parameters
m_Animator.SetFloat("Forward", m_ForwardAmount, 0.1f, Time.deltaTime);
m_Animator.SetFloat("Turn", m_TurnAmount, 0.1f, Time.deltaTime);
m_Animator.SetBool("Crouch", m_Crouching);
m_Animator.SetBool("OnGround", m_IsGrounded);
if (!m_IsGrounded)
{
m_Animator.SetFloat("Jump", m_Rigidbody.velocity.y);
}
// calculate which leg is behind, so as to leave that leg trailing in the jump animation
// (This code is reliant on the specific run cycle offset in our animations,
// and assumes one leg passes the other at the normalized clip times of 0.0 and 0.5)
float runCycle =
Mathf.Repeat(
m_Animator.GetCurrentAnimatorStateInfo(0).normalizedTime + m_RunCycleLegOffset, 1);
float jumpLeg = (runCycle < k_Half ? 1 : -1) * m_ForwardAmount;
if (m_IsGrounded)
{
m_Animator.SetFloat("JumpLeg", jumpLeg);
}
// the anim speed multiplier allows the overall speed of walking/running to be tweaked in the inspector,
// which affects the movement speed because of the root motion.
if (m_IsGrounded && move.magnitude > 0)
{
m_Animator.speed = m_AnimSpeedMultiplier;
}
else
{
// don't use that while airborne
m_Animator.speed = 1;
}
}
void HandleAirborneMovement()
{
// apply extra gravity from multiplier:
Vector3 extraGravityForce = (Physics.gravity * m_GravityMultiplier) - Physics.gravity;
m_Rigidbody.AddForce(extraGravityForce);
m_GroundCheckDistance = m_Rigidbody.velocity.y < 0 ? m_OrigGroundCheckDistance : 0.01f;
}
void HandleGroundedMovement(bool crouch, bool jump)
{
// check whether conditions are right to allow a jump:
if (jump && !crouch && m_Animator.GetCurrentAnimatorStateInfo(0).IsName("Grounded"))
{
// jump!
m_Rigidbody.velocity = new Vector3(m_Rigidbody.velocity.x, m_JumpPower, m_Rigidbody.velocity.z);
m_IsGrounded = false;
m_Animator.applyRootMotion = false;
m_GroundCheckDistance = 0.1f;
}
}
void ApplyExtraTurnRotation()
{
// help the character turn faster (this is in addition to root rotation in the animation)
float turnSpeed = Mathf.Lerp(m_StationaryTurnSpeed, m_MovingTurnSpeed, m_ForwardAmount);
transform.Rotate(0, m_TurnAmount * turnSpeed * Time.deltaTime, 0);
}
public void OnAnimatorMove()
{
// we implement this function to override the default root motion.
// this allows us to modify the positional speed before it's applied.
if (m_IsGrounded && Time.deltaTime > 0)
{
Vector3 v = (m_Animator.deltaPosition * m_MoveSpeedMultiplier) / Time.deltaTime;
// we preserve the existing y part of the current velocity.
v.y = m_Rigidbody.velocity.y;
m_Rigidbody.velocity = v;
}
}
void CheckGroundStatus()
{
RaycastHit hitInfo;
#if UNITY_EDITOR
// helper to visualise the ground check ray in the scene view
Debug.DrawLine(transform.position + (Vector3.up * 0.1f), transform.position + (Vector3.up * 0.1f) + (Vector3.down * m_GroundCheckDistance));
#endif
// 0.1f is a small offset to start the ray from inside the character
// it is also good to note that the transform position in the sample assets is at the base of the character
if (Physics.Raycast(transform.position + (Vector3.up * 0.1f), Vector3.down, out hitInfo, m_GroundCheckDistance))
{
m_GroundNormal = hitInfo.normal;
m_IsGrounded = true;
m_Animator.applyRootMotion = true;
}
else
{
m_IsGrounded = false;
m_GroundNormal = Vector3.up;
m_Animator.applyRootMotion = false;
}
}
}
}
I'm working on a project where I'm trying to make my character move by jumping at an angle. Right now during the frame updates, the character will pivot back and forth and when the right key is pressed, they will jump. This code causes them to jump at an angle, but they always return to their original position.
Additionally, I have two characters who start on opposite sides of the stage, but when I start the game they teleport to the same position. I've spent a lot of time reviewing my code but I can't seem to get this to work. Any help you can provide?
using UnityEngine;
using System.Collections;
public class Freg : MonoBehaviour {
public GameObject Tounge;
public float gravity;
public float tempScale = 1;
public float MaxJump = 8f;
public float MinJump = 0.1f;
static float yVector = 0;
static float xVector = 0;
static bool grounded = true;
bool isleft = false;
Vector3 farthestleft;
Vector3 farthestright;
// Use this for initialization
void Start () {
farthestleft = new Vector3 (-33.7f, 50.2f, 24.8f);
farthestright = new Vector3 (22.56f, 54.83f, -15.12f);
}
void OnTriggerEnter (Collider other) {
if (other.GetComponent<Collider> ().tag == "Ground") {
grounded = true;
yVector = 0;
//xVector = 0;
Vector3 onGround = new Vector3 (transform.position.x, -4.86f, transform.position.z);
transform.position = onGround;
} else
grounded = false;
}
// Update is called once per frame
void Update () {
/*if (Input.GetKey (KeyCode.UpArrow) == true) {
Tounge.transform.localScale.Set (1, 0.5f, 1);
} else {
Tounge.transform.localScale.Set (1, 1, 1);
}*/
if (grounded == false) {
yVector -= gravity;
}
if (Input.GetKeyDown (KeyCode.UpArrow) == true && grounded == true) {
MinJump += 0.5f;
} else if (MinJump > 0.1f){
yVector += MinJump;
xVector += MinJump;
MinJump = 0.1f;
grounded = false;
}
Vector3 stuff = new Vector3 (transform.localPosition.y + xVector, transform.position.y + yVector, transform.position.z);
transform.position = stuff;
float t = Mathf.PingPong (Time.time * 0.5f * 2.0f, 1.0f);
transform.eulerAngles = Vector3.Lerp (farthestright, farthestleft, t);
}
}
it looks like you should update the current position during the if statements, rather than after that way on each update, the actual position is moving based on the decision rather than just the end of the loop.