Made two scripts for opening door when button is pressed. The problem is door opens from any distance, and I need it opens only when player press button in front of a door.
Here is first script what attached to a Camera of FPS controller char.
public class DoorRayCast : MonoBehaviour
{
public float Doordistance = 1.5f;
private bool reachindDoor = false;
void Start ()
{
}
private IEnumerator isDoorClose ()
{
while (true)
{
if (Input.GetButtonDown("actButton"))
{
if (!reachindDoor)
checkForDoor();
else
reachindDoor = false;
}
yield return null;
}
}
private void checkForDoor ()
{
Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));
RaycastHit data;
if (Physics.Raycast (ray, out data, Doordistance))
{
if (data.transform.tag == "door")
{
reachindDoor = true;
GetComponent<DoorsActAnim>();
return;
}
}
reachindDoor = false;
}
}
And a second one what starts an animation.
public class DoorsActAnim : MonoBehaviour
{
private Animator DoorAnim;
private AnimatorStateInfo BaseLayer;
private AnimatorStateInfo currentBaseState;
static int idleDoor = Animator.StringToHash("Base Layer.apartment_door_idle");
static int openDoor = Animator.StringToHash("Base Layer.apartment_door_open");
static int closeDoor = Animator.StringToHash("Base Layer.apartment_door_close");
public float Doordistance = 1.5f;
public AudioClip openDoorSound;
public AudioClip closeDoorSound;
private AudioSource DoorSound;
// Use this for initialization
void Start()
{
DoorAnim = GetComponent<Animator>();
DoorSound = GetComponent<AudioSource>();
}
void FixedUpdate()
{
currentBaseState = DoorAnim.GetCurrentAnimatorStateInfo(0);
if (Input.GetButtonDown("actButton"))
{
DoorSound.PlayOneShot(openDoorSound);
if (currentBaseState.nameHash == closeDoor)
{
DoorAnim.SetTrigger("Open");
DoorSound.PlayOneShot(openDoorSound);
}
else
{
DoorAnim.SetTrigger("Close");
DoorSound.PlayOneShot(closeDoorSound);
}
}
}
}
I know the trouble is in in DoorActAnim Script in the if (Input.GetButtonDown(“actButton”)) part just don’t know how to fix it, and make it right. I am a newbie in Scripting.
that script does nothing about checking the distance… so it will always work. Both scripts are working independantly of each other.
I think you are trying to make the first script tell the second script “do something”. In which case you need to create a function, not use an Update in DoorsActAnim
and then you can use
(“get me the component”, “ok, now what?”… “and now do this thing”)
this way the input is checked for distance in the first script, if it’s within range and any other prerequisites are met the animation handler script is told to do something i.e. open the door.
Change FixedUpdate in the second script to just Update, first off- there’s no physics in there, so it’s better to just run it all once per frame like normal. IsDoorClose() is currently running every single frame, infinitely. In that situation, there’s no reason to incur the overhead of a coroutine- just make it a normal function and have it called every frame in Update() instead. None of this is important now, because you need to delete most of it anyways.
Now, as for the distance problem, both scripts have independent actions that occur when a single button is pressed. The action in the door’s animation script has no dependence on anything except that button press. What you need to do is move the entirety of that into a new function called “ToggleDoor”, which you’ll then call from “data.GetComponent().ToggleDoor();” in your raycast. In fact, just move the “If GetButtonDown” into that raycast and call the function only if the raycast results are tagged “door” AND the button is pressed.
Yup, I was wrong- I thought you could just get the GameObject directly, but this way works. You haven’t shown us the script that has the ToggleDoor() function in it though, so copy that over.
The string tag on the door has to be exactly right (right capitalization too), your button press “actButton” has to be in the Input list in Unity, the distance has to be great enough to actually be able to reach the door (try removing the distance completely for a minute, as that will set it to “infinity” by default), you need to have a box collider on the door object (which is NOT set to “trigger”, if you don’t have Edit => Project Settings => Physics set to “raycast hit triggers”), the door object and its collider both have to be active.
If none of that works, put some Debug.Logs in the code after every conditional statement to see where it’s being foiled.
public class DoorRayCast : MonoBehaviour
{
public float RayDistanse = 0f;
void Start()
{
}
void Update()
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, RayDistanse))
{
if (hit.transform.tag == "DoorTag")
{
if (Input.GetButtonDown("actButton"))
{
//hit.collider.enabled = true;
hit.collider.GetComponent<DoorsActAnim>().ToggleDoor();
Debug.Log("Input hit");
}
Debug.Log("hit Ray");
}
Debug.Log("hit Ray 01");
}
//Debug.Log("Start");
}
}
I checked all with a debug, problem starts some where in this part of code, but I can’t understand where everything is set up right I checked settings and tags like 5 times, even changed some of them for incase.
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, RayDistanse))
{
if (hit.transform.tag == "DoorTag")
{
I didn’t mean to set the RayDistanse variable to 0f, that’ll literally not move anywhere. You need to remove the variable entirely from the raycast so there’s only a ray and a hit, or change “RayDistanse” to “Mathf.Infinity” in the raycast- which will do exactly the same thing.
Anyways, that’ll only tell you if this is the part that was going wrong- you’ll be back to being able to activate it from any distance- though you’ll at least have to be looking right at it. If that is the problem, then you need to just keep adjusting the distance until you’ve got it set to something that works, but is reasonably close.
I just noticed that you switched over to using ScreenPointToRay- is there actually a cursor on the screen? I had assumed that this was first person, so ViewportPointToRay how you had it was fine. Also, is the current camera the only camera? Instead of using Camera.main you can just grab the GetComponent() to make sure that the proper camera is the one being raycasted from (assuming this script is attached to the camera object).
You put it back in FixedUpdate- there’s no physics here, so leave it in Update. When you do ViewportPointToRay, you need to use .5f for the x and y values to mean “middle of the screen”. It looked like you had an extra “}” in there after everything else. DoorsActAnim needs to be the name of the class and the file of the animation script you made, it needs to be properly spelled and capitalized, it needs to be attached to the same object (the door) that the collider is attached to, and it needs to be enabled.
void Update()
{
RaycastHit hit;
Ray ray = GetComponent<Camera>().ViewportPointToRay(new Vector3(.5f, .5f, 0f));
if (Physics.Raycast(ray, out hit, RayDistance))
{
if (hit.transform.tag == "DoorTag")
{
if (Input.GetButtonDown("actButton"))
{
hit.collider.GetComponent<DoorsActAnim>().ToggleDoor();
}
}
}
}