Code is acting different depending on call
Here are the simple code bits:
void Update() {
if(isTeleporting) {
teleport(new Vector3(transform.position.x, transform.position.y, transform.position.z - 1));
}
if (Input.GetKey(KeyCode.F)) {
teleport(new Vector3(transform.position.x, transform.position.y, transform.position.z - 1));
}
}
Every frame this checks if an 'isTeleporting' variable is true, if it is, it will call the teleport method. It also checks if I hit the 'F' key, if I do, it does the exact same code.
Teleport method:
public void teleport(Vector3 pos) {
isTeleporting = false;
Debug.Log("Teleport!");
transform.position = new Vector3(pos.x, pos.y, pos.z);
}
Pretty simple, it sets the 'isTeleporting' back to false so it doesn't teleport every frame, prints a debug, and finally actually moves the object.
So, how does 'isTeleporting' become true? If I come in contact with a trigger.
public GameObject[] startLocs;
public bool isTeleporting = false;
void OnTriggerEnter(Collider col) {
for (int i = 0; i < startLocs.Length; i++) {
if (col.gameObject == startLocs[i]) {
Debug.Log("Player entered: " + col.gameObject.tag + " " + i);
isTeleporting = true;
}
}
}
If the player triggers a startLocs trigger, then it will proceed to set isTeleporting to true.
Basically, all this is me trying to set up a door system. I've tried a million different ways but for some reason the player is not moving. The debug positions say the positions are changing, but he is in the same place.
The problem with this code is, when I come in contact with a door with a trigger, it calls the teleport method (because 'isTeleport' is set to true) and prints the debug "Teleport!" statement, but player does not move. Yet, when I hit the 'F' key, it again prints the debug "Teleport!" statement, except this time, the player does move. Why does this happen? And how can I fix this?
Any help is appreciated.
What are you using to control your character? The built in first/third person controller, or something you wrote yourself?
Something I wrote myself. Here are the $$anonymous$$imal basics:
private float inc;
public bool is$$anonymous$$oving;
public Vector3 startPoint;
public Vector3 endPoint;
void Start() {
startPoint = transform.position;
endPoint = transform.position;
}
void Update() {
if (inc <= 1 && is$$anonymous$$oving) {
inc += speed / 100;
} else {
is$$anonymous$$oving = false;
}
if (is$$anonymous$$oving) { //I suspect this is the cause?
transform.position = Vector3.Lerp(startPoint, endPoint, inc);
}
//Likewise for the other directions, modifying the endpoint's x or z by plus or $$anonymous$$us 1
if ((Input.Get$$anonymous$$ey("w") || Input.Get$$anonymous$$ey($$anonymous$$eyCode.UpArrow)) && !is$$anonymous$$oving) {
inc = 0;
is$$anonymous$$oving = true;
startPoint = transform.position;
endPoint = new Vector3(transform.position.x, transform.position.y, transform.position.z + 1);
}
}
Player has a Rigidbody and a Box Collider. This is also a tile-based RPG top down game.
Yes, your lerp might be the problem. When you push a movement button ('w' for instance), your lerp endpoint gets set to your current position + 1 on the Z axis. This endpoint remains the same until your "inc" variable is greater than 1, which could take many frames, depending on the speed variable. Your teleport is an instantaneous move of 1 unit in the -z direction, so it probably does actually teleport, but it is then moved back to whatever the current lerp position is, making it appear as though no teleport has occured.
I'll try to test this to see if that is actually what is happening.
Answer by Ahndrakhul · Jun 23, 2016 at 08:46 AM
I couldn't respond to your last comment below the main question, so I will put this here. It might be best to stop player movement when you enter a teleport trigger. That way, you can just do the instantaneous teleport and not worry about all the sliding about through other triggers.
These scripts might work for you with a little bit of modification. Basically, the teleport trigger objects each need to have a script that has a vector 3 destination variable. The player has a playercontrol script for movement and a teleport script for teleporting. When the player enters a teleport trigger(tagged with "TeleportTrigger"), movement is stopped with a call to StopMoving() on the PlayerControl script, then the player is teleported to whatever the destination is that is contained in trigger object's TeleportTrigger script. This uses a coroutine for movement and "MoveTowards" instead of lerp. Hope it helps.
For Movement (attached to the player):
using UnityEngine;
using System.Collections;
public class PlayerControl : MonoBehaviour
{
public float speed = 5.0f;
public bool isMoving = false;
void Update()
{
if ((Input.GetKey("w") || Input.GetKey(KeyCode.UpArrow)))
{
StartMoving(Vector3.forward, 1);
}
if ((Input.GetKey("s") || Input.GetKey(KeyCode.DownArrow)))
{
StartMoving(Vector3.back, 1);
}
if ((Input.GetKey("a") || Input.GetKey(KeyCode.LeftArrow)))
{
StartMoving(Vector3.left, 1);
}
if ((Input.GetKey("d") || Input.GetKey(KeyCode.RightArrow)))
{
StartMoving(Vector3.right, 1);
}
}
void StartMoving(Vector3 direction, float distance)
{
if (!isMoving)
{
isMoving = true;
StartCoroutine(Move(transform.position + (direction * distance)));
}
}
public void StopMoving()
{
isMoving = false;
StopAllCoroutines();
}
IEnumerator Move(Vector3 targetPosition)
{
float step = speed * Time.deltaTime;
while (isMoving && (transform.position != targetPosition))
{
transform.position = Vector3.MoveTowards(transform.position, targetPosition, step);
yield return null;
}
isMoving = false;
}
}
For Teleportation (attached to the player):
using UnityEngine;
public class TeleportControl : MonoBehaviour
{
void Teleport(Vector3 destination)
{
transform.position = destination;
}
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("TeleportTrigger"))
{
GetComponent<PlayerControl>().StopMoving();
Teleport(other.GetComponent<TeleportTrigger>().teleportDestination);
}
}
}
Teleport Destination (attached to teleport trigger object):
using UnityEngine;
public class TeleportTrigger : MonoBehaviour
{
//set this in the inspector for each trigger object
public Vector3 teleportDestination;
}
Thank you very much for taking the time and going beyond what is expected. This code is working much better than the lerp. I was able to use this as a base and add the rest of the code in and now it is much improved. Thank you.
Answer by JimNero009 · Jun 22, 2016 at 09:38 PM
I'm afraid I haven't got an answer for you but I do have a comment that may or may not fix the issue - instead of playing around with this public bool, why not just call the teleport function straight off when the collision is detected?
public GameObject[] startLocs;
public bool isTeleporting = false;
void OnTriggerEnter(Collider col) {
for (int i = 0; i < startLocs.Length; i++) {
if (col.gameObject == startLocs[i]) {
Debug.Log("Player entered: " + col.gameObject.tag + " " + i);
// Set up a reference to the object where the teleport function is attached and call that function here
}
}
}
Then you can just keep the 'if F key is pushed down' one as is, since this works already, in the update function.
Thanks for the response, but I've tried calling it directly before. I've tried calling the teleport method right when it triggers, and I've tried just having the teleport method's code in the trigger's method. I can't get either of these to actually move the player object. This ugly public bool is probably the 15th different attempt I have tried to set it up. Ideally, I would like a separate script just for the teleportations that I attach to the player (rather than including it in the player's main code which handles input). This would handle the start and end locations, and the direction the player faces, etc. Unfortunately, I can't get it to move the player. I've tried forces, setting the position equal to a Vector3, using the move method in the Rigidbody, even destroying and instantiating the player in the desired position (which worked, but brought upon other problems). Something like teleportation seems so simple, I can't figure out why I'm not getting it to work.