Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Cepheron · Jan 03, 2021 at 09:06 PM · raycastingevent triggeringkeypressactivate

Activate event on key press?

I've been trying to figure out how to get something to happen on a key press (like the typical "Press E to use" in games) but only have something happen when faced with the object I want to be used in stead of the event happening anywhere I press the button. So for reference, currently I have a plant that gets picked when pressing "E". I also want to use "E" to activate a bed and sleep (currently just makes the screen black with a UII image). I have been using Raycast for these things so pressing "e" only works on the objects with the correct scripts. The problem occurs when trying to use "E" for multiple things. It doesn't work and I assume it's because of how raycasting works. I know there must be some way to activate objects and events using a better method...but how does one do that?

The two scripts I'm using:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class Player : MonoBehaviour
 {
     [SerializeField] Camera FPCamera;
     [SerializeField] float range = 5f;
 
     WildPlants plantTarget;
     Sleep sleepTarget;
 
     void Start()
     {
         plantTarget = GetComponent<WildPlants>();
         sleepTarget = GetComponent<Sleep>();
     }
 
     void Update()
     {
         PressUseKey();
     }
 
     public void PressUseKey()
     {
         if (Input.GetKeyDown(KeyCode.E))
         {
             RaycastHit hit;
             var raycastThing = Physics.Raycast(FPCamera.transform.position, FPCamera.transform.forward, out hit, range);
             if (raycastThing)
             {                
                 WildPlants plantTarget = hit.transform.GetComponent<WildPlants>();
                 if (plantTarget == null) { return; }
                 plantTarget.ProcessPlantPicking();
             }            
             else { return; }
         }
         /*if (Input.GetKeyDown(KeyCode.E))
         {
             RaycastHit hit;
             if (Physics.Raycast(FPCamera.transform.position, FPCamera.transform.forward, out hit, range))
             {                
                 Sleep sleepTarget = hit.transform.GetComponent<Sleep>();                
                 if (sleepTarget == null) { return; }                
                 sleepTarget.Fade();
                 print("does it work?");
             }
             else { return; }
         }*/
     }
 }

And:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class WildPlants : MonoBehaviour
 {
     [SerializeField] float growthRate = 5f;
     [SerializeField] GameObject grownPlant;
     [SerializeField] GameObject pickedPlant;
     [SerializeField] Collider emptyCollider;
 
     [SerializeField] bool isPicked = false;
 
     Renderer cubeRenderer;    
 
     void Start()
     {
         emptyCollider = GetComponent<Collider>();
         cubeRenderer = grownPlant.GetComponent<Renderer>();       
         isPicked = false;
         cubeRenderer.material.SetColor("_Color", Color.green);       
     }
     
     void Update()
     {
         
     }    
     
     public void ProcessPlantPicking()
     {
         if (isPicked == false)
         {
             StartCoroutine(PlantIsPicked());            
             print("Plant put in inventory");
         }
         else if (isPicked == true)
         {
             return;
         }        
     }
 
     IEnumerator PlantIsPicked()
     {
         //cubeRenderer.material.SetColor("_Color", Color.red);         
         grownPlant.SetActive(false);
         emptyCollider.enabled = false;
         pickedPlant.SetActive(true);
         yield return new WaitForSecondsRealtime(growthRate);
         isPicked = false;
         emptyCollider.enabled = true;
         grownPlant.SetActive(true);
         pickedPlant.SetActive(false);        
     }    
 }




Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by yummy81 · Jan 04, 2021 at 12:20 AM

Use interfaces. I will show you general idea, and then you will be able to built your system upon it. So, at first create interface. I called it IInteractable and it has one method - DoSomething. You can put it in any script you like - I put it just below your Player class in Player script. It means that every class which want to implement the IInteractable interface is forced to create DoSomething method. So, I make your WildPlants and Sleep classes implement it. Finally, when you press E you search for IInteractable component. As WildPlants and Sleep implement this interface, Unity will invoke proper method from proper class. Player script:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class Player : MonoBehaviour
 {
     [SerializeField] Camera FPCamera;
     [SerializeField] float range = 100f;
     
     void Update()
     {
         if (Input.GetKeyDown(KeyCode.E))
         {
             RaycastHit hit;
             var raycastThing = Physics.Raycast(FPCamera.transform.position, FPCamera.transform.forward, out hit, range);
             
             if (raycastThing)
             {
                 IInteractable interactable = hit.transform.GetComponent<IInteractable>();
                 
                 if (interactable!=null)
                     interactable.DoSomething();
             }
         }
     }
 }
 
 public interface IInteractable
 {
     void DoSomething();
 }

WildPlants script:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class WildPlants : MonoBehaviour, IInteractable
 {
     public void DoSomething()
     {
         Debug.Log("WildPlants");
     }
 
 }

Sleep script:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class Sleep : MonoBehaviour, IInteractable
 {
     public void DoSomething()
     {
         Debug.Log("Sleep");
     }
 }
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Cepheron · Jan 04, 2021 at 04:00 PM 0
Share

Thanks for this! Very helpful for a newbie like me!

avatar image Cepheron · Jan 04, 2021 at 08:45 PM 0
Share

Ok I guess I've run into a snag already just trying to implement the interface. When I put it next to $$anonymous$$onobehavior in WildPlants it just gives a red squiggle and acts like it doesn't know what it is.

avatar image
0

Answer by Zaeran · Jan 04, 2021 at 12:18 AM

Raycasting is what you'll need know what object to press. You can probably just put a single forward raycast in every frame if you want the 'press E' prompt to appear.

You can have one script that tests every possible script, but that's not efficient at all, and is almost guaranteed to lead to spaghetti code. You'd be better off either using an interface with the Interact method in it, and then each object's script will use that interface. That way, you can just check if what you're pointing at is has the interface, and just call the Interact method if it does.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Cepheron · Jan 04, 2021 at 04:00 PM 0
Share

Thanks that's super helpful! I'm pretty new to coding so I don't know everything I can do, and Interact seems like it's exactly what I need!

avatar image
0

Answer by Cepheron · Jan 04, 2021 at 08:43 PM

I compared with other scripts to make sure I at least typed it all correctly and it does appear I have. I have named the methods the generic stuff you had in your example just for testing What am I missing here?

Player

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class Player : MonoBehaviour
 {
     [SerializeField] Camera FPCamera;
     [SerializeField] float range = 5f;
 
     WildPlants plantTarget;
     Sleep sleepTarget;
 
     void Start()
     {
         plantTarget = GetComponent<WildPlants>();
         sleepTarget = GetComponent<Sleep>();
     }
 
     void Update()
     {
         PressUseKey();
     }
 
     public interface Interactables
     {
         void DoSomething();
     }
 
     public void PressUseKey()
     {
         if (Input.GetKeyDown(KeyCode.E))
         {
             RaycastHit hit;
             var raycastThing = Physics.Raycast(FPCamera.transform.position, FPCamera.transform.forward, out hit, range);
             if (raycastThing)
             {
                 Interactables interactable = hit.transform.GetComponent<Interactables>();
 
                 if (interactable != null)
                 interactable.DoSomething();
             }
             else { return; }
         }
         /*if (Input.GetKeyDown(KeyCode.E))
         {
             RaycastHit hit;
             if (Physics.Raycast(FPCamera.transform.position, FPCamera.transform.forward, out hit, range))
             {                
                 Sleep sleepTarget = hit.transform.GetComponent<Sleep>();                
                 if (sleepTarget == null) { return; }                
                 sleepTarget.Fade();
                 print("does it work?");
             }
             else { return; }
         }*/
 
     }
 
     
 }

WildPlants

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class WildPlants : MonoBehaviour, Interactables
 {
     [SerializeField] float growthRate = 5f;
     [SerializeField] GameObject grownPlant;
     [SerializeField] GameObject pickedPlant;
     [SerializeField] Collider emptyCollider;
 
     [SerializeField] bool isPicked = false;
 
     Renderer cubeRenderer;    
 
     void Start()
     {
         emptyCollider = GetComponent<Collider>();
         cubeRenderer = grownPlant.GetComponent<Renderer>();       
         isPicked = false;
         cubeRenderer.material.SetColor("_Color", Color.green);       
     }
 
     void Update()
     {
 
     }    
 
     public void DoSomething()
     {
         Debug.Log("WildPlants");
     }
     
     public void ProcessPlantPicking()
     {
         if (isPicked == false)
         {
             StartCoroutine(PlantIsPicked());            
             print("Plant put in inventory");
         }
         else if (isPicked == true)
         {
             return;
         }        
     }
 
     IEnumerator PlantIsPicked()
     {
         //cubeRenderer.material.SetColor("_Color", Color.red);         
         grownPlant.SetActive(false);
         emptyCollider.enabled = false;
         pickedPlant.SetActive(true);
         yield return new WaitForSecondsRealtime(growthRate);
         isPicked = false;
         emptyCollider.enabled = true;
         grownPlant.SetActive(true);
         pickedPlant.SetActive(false);        
     }    
 }






Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image yummy81 · Jan 04, 2021 at 09:15 PM 0
Share

You put interface declaration inside your Player class:

 public class Player : $$anonymous$$onoBehaviour
 // your code
     public interface Interactables
     {
         void DoSomething();
     }
 // your code
 }
 

If you do this that way you should implement interface as follows:

 public class WildPlants : $$anonymous$$onoBehaviour, Player.Interactables
 

But if you look at my example once again, you will see that I put the declaration outside the Player class. Of course that depends on you where you want to place the code. If it's inside the class it must be Player.Interactables. If outside, then Interactables is enough.

avatar image Cepheron yummy81 · Jan 05, 2021 at 01:34 AM 0
Share

Oooh I didn't realize it was actually after the very last bracket, whoops! $$anonymous$$y bad

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

117 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Raycast rotating with object rotating 1 Answer

(C#) Collider to collider2d 0 Answers

Raycasting not working properly 0 Answers

Using a raycast's direction in parent's Y-rotation 1 Answer

Getting the object reference not set to an instance of an object error when raycasting 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges