How can I implement a GUITexture for picking up an object?
The problem is I have a GetButtonUp input, how can I change it to GUI Button?
The use is a layer type of my tag type. Here is the code:
#pragma strict
var Primary : Item; //Your Primary item holder
var Secondary : Item; //Your Secondary item holder
var myLayerMask : LayerMask;
private var HitItem : GameObject; //Item that raycast hits.
function Update ()
{
if(Input.GetButtonUp("Use")) //Remember to make new Input called "Use" :)
{
var hit: RaycastHit;
var Direction = transform.TransformDirection(Vector3.forward);
Debug.DrawRay(transform.position, Direction * 2.5, Color.blue); //Shows raycast when you press "Use"
if(Physics.Raycast(transform.position, Direction, hit, 2.5, myLayerMask))
{
if(hit.transform.tag == "Item") //If raycast hits transform.tag "Item".
{
HitItem = hit.transform.gameObject; //HitItem becomes hit.gameObject.
var ItemScr : ItemScript = HitItem.GetComponent("ItemScript");
if(ItemScr.MyItem.IsSecondary) //If Hit item is Secondary
{
if(Secondary.ActiveObj == null) //Checks if you dont have Secondary Item
{
Secondary = ItemScr.MyItem;
Destroy(hit.transform.gameObject);
if(Primary.ActiveObj == null) //Checks if you have already
{ //equipped item in your hand.
Secondary.ActiveObj.active = true;
}
else if(Primary.ActiveObj)
{
if(Primary.ActiveObj.active == false)
{
Secondary.ActiveObj.active = true;
}
}
}
}
//And same to primary :)
if(!ItemScr.MyItem.IsSecondary) //If Hit item is Primary
{
if(Primary.ActiveObj == null) //If you don't have primary, goes on...
{
Primary = ItemScr.MyItem;
Destroy(hit.transform.gameObject);
if(Secondary.ActiveObj == null)
{
Primary.ActiveObj.active = true;
}
else if(Secondary.ActiveObj)
{
if(Secondary.ActiveObj.active == false)
{
Primary.ActiveObj.active = true;
}
}
}
}
}
}
}
}
Any call with GUI needs to be called in the OnGUI() method. And usually GUI scripts are put separate from other parts of your program and attached to the main camera or an empty object.
-Personally I use main camera.
Unity had a good walk through Here
And if you want to change to c# i suggest google, which I believe should be a perfect source for this type of question.
Related
I'm trying to make a pickup system and I thought it would be cool to do an outline around the item when you're looking at it. The issue I'm facing though is when you're no longer looking at the object I need to disable the outline. I ended up doing an odd solution and would like to get some help improving it.
public class PlayerCamera : MonoBehaviour
{
public Transform playerBody;
public Transform cameraHolder;
public float sensitivity;
public float currentY;
void Update()
{
MoveCamera();
LookingAtObject();
}
Outline objectOutline;
void LookingAtObject()
{
if(Physics.Raycast(cameraHolder.transform.position, cameraHolder.transform.forward, out var hit, Mathf.Infinity))
{
var obj = hit.collider.gameObject;
var outline = obj.GetComponent<Outline>();
if (obj && outline)
{
objectOutline = hit.transform.GetComponent<Outline>();
if (objectOutline)
objectOutline.OutlineWidth = 7;
}
else if (objectOutline)
objectOutline.OutlineWidth = 0;
}
}
}
You can store the outlined object in a variable, and whenever you hit a different outline object or hit nothing, set the outline back to zero.
Outline objectOutline;
void LookingAtObject()
{
if (Physics.Raycast(...))
{
var outline = hit.collider.GetComponent<Outline>();
// Make sure the hit object is not the same one we already outlined
//
if (outline != objectOutline)
{
// Remove the outline from our previously viewed object
//
if (objectOutline != null)
{
objectOutline.OutlineWidth = 0;
}
// Store the new outline object
//
objectOutline = outline;
// Since outline could be null, we need to check null before outlining
//
if (objectOutline != null)
{
objectOutline.OutlineWidth = 7;
}
}
}
// If we have an object we outlined and we didnt hit anything,
// remove the outline and reset the variable
//
else if (objectOutline != null)
{
objectOutline.OutlineWidth = 0;
objectOutline = null;
}
}
You need two events to solve the problem. Input frame and ray output frame. This code detects which raycast event is by recording the previous raycastHit frame and comparing it to the current hit, and sets the outline accordingly.
private RaycastHit lastHit;
void Update()
{
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Physics.Raycast(ray, out var hit);
//Physics.Raycast(cameraHolder.transform.position, cameraHolder.transform.forward, out var hit, Mathf.Infinity);
if (hit.transform != lastHit.transform)
{
if (hit.transform) // when raycast Begin
{
var outline = hit.transform.GetComponent<Outline>();
outline.OutlineWidth = 7;
}
else if (lastHit.transform) // when raycast out
{
var outline = lastHit.transform.GetComponent<Outline>();
outline.OutlineWidth = 0;
}
}
lastHit = hit;
}
Hint: I commented on your raycast code for testing. If you want to change the raycast code as before.
I am looking to show a line in my app from where the model is placed so that the user knows position where the model is kept in real world. When user changes device camera away from model the line gets turned on to show where the model is. Similarly it turns off when model is detected. I have attached images to show from a similar app white dotted lines show the path. Notice how the lines disappear when the model is detected.
LineRenderer lins;
public GameObject Lineprefab;
private GameObject newline;
public Transform startpoint;
public Renderer m_rend1;
bool HitTestWithResultType (ARPoint point, ARHitTestResultType resultTypes)
{
List<ARHitTestResult> hitResults = UnityARSessionNativeInterface.GetARSessionNativeInterface ().HitTest (point, resultTypes);
if (hitResults.Count > 0 && check==true)
{
foreach (var hitResult in hitResults)
{
Debug.Log ("Got hit!");
//obj.Hideplane();
Genplanes.SetActive(false);
if (Select == 0) {
Debug.Log("hit-zero!");
Instantiate(Instaobj[0], ForSelect);
check = false;
}
if (Select == 1) {
Debug.Log("hit-one!");
Instantiate(Instaobj[1], ForSelect);
check = false;
}
if (Select == 2) {
Debug.Log("hit-two!");
Instantiate(Instaobj[2], ForSelect);
check = false;
}
m_HitTransform.position = UnityARMatrixOps.GetPosition (hitResult.worldTransform);
m_HitTransform.rotation = UnityARMatrixOps.GetRotation (hitResult.worldTransform);
Debug.Log (string.Format ("x:{0:0.######} y:{1:0.######} z:{2:0.######}", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z));
obj.StopPlaneTracking();
}
}
return false;
}
private void Start()
{
spawngenerator();
newline.SetActive(false);
m_rend1 = GetComponent<MeshRenderer>();
}
void spawngenerator()
{
GameObject newline = Instantiate(Lineprefab);
lins = newline.GetComponent<LineRenderer>();
}
private void LateUpdate()
{
lins.SetPosition(0, startpoint.position);
lins.SetPosition(1, m_HitTransform.position);
if( m_rend1.isVisible==true)
{
Debug.Log("Render is Visible");
newline.SetActive(false);
}
else if( m_rend1.isVisible==false)
{
newline.SetActive(true);
Debug.Log("It is InVisible");
Debug.Log("Render is InVisible");
}
}
void Update () {
#if UNITY_EDITOR //we will only use this script on the editor side, though there is nothing that would prevent it from working on device
if (Input.GetMouseButtonDown (0)) {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
//we'll try to hit one of the plane collider gameobjects that were generated by the plugin
//effectively similar to calling HitTest with ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingExtent
if (Physics.Raycast (ray, out hit, maxRayDistance, collisionLayer)) {
//we're going to get the position from the contact point
m_HitTransform.position = hit.point;
Debug.Log (string.Format ("x:{0:0.######} y:{1:0.######} z:{2:0.######}", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z));
//and the rotation from the transform of the plane collider
m_HitTransform.rotation = hit.transform.rotation;
}
}
#else
if (Input.touchCount > 0 && m_HitTransform != null )
{
var touch = Input.GetTouch(0);
if ((touch.phase == TouchPhase.Began || touch.phase == TouchPhase.Moved) && !EventSystem.current.IsPointerOverGameObject(touch.fingerId))
{
var screenPosition = Camera.main.ScreenToViewportPoint(touch.position);
ARPoint point = new ARPoint {
x = screenPosition.x,
y = screenPosition.y
};
// prioritize reults types
ARHitTestResultType[] resultTypes = {
//ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingGeometry,
ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingExtent,
// if you want to use infinite planes use this:
//ARHitTestResultType.ARHitTestResultTypeExistingPlane,
//ARHitTestResultType.ARHitTestResultTypeEstimatedHorizontalPlane,
//ARHitTestResultType.ARHitTestResultTypeEstimatedVerticalPlane,
//ARHitTestResultType.ARHitTestResultTypeFeaturePoint
};
foreach (ARHitTestResultType resultType in resultTypes)
{
if (HitTestWithResultType (point, resultType))
{
return;
}
}
}
}
#endif
}
.
First, I 'd start with checking if the model is within the bounding box of the camera https://docs.unity3d.com/ScriptReference/Renderer-isVisible.html
if the object is not visible (isVisible == false), create a line renderer from object position to wherever it should end.
The end point could be a camera child place just in front of it, so it looks like it starts from the user to the object.
I have a target object (cube), and a fake mouse that I created from an object (sphere) to be controlled by gamepad joystick. I want to bring out another object (let say; sphere), when I push the gamepad button and precisely hit the target object (cube).
Before, I have tried with a mouse click, and it succeeds, but when I controlled the fake mouse with a joystick, when I press the button even outside the target (cube) it still brings out another object. Here is the code, if anybody can help me to revise it. Thanks
function Start () {}
function Update () {
if (Input.GetButtonDown ("Fire1"))
{
var Cube = GameObject.FindGameObjectsWithTag ("Cube");
if (Cube[0].GetComponent(MeshRenderer).enabled){
var Circle1 = GameObject.FindGameObjectsWithTag ("Circle1");
Circle1[0].GetComponent(MeshRenderer).enabled = true;
Circle1[0].GetComponent(MeshRenderer).material.color = color.red;
}
}
}
[solved]
Thanks to EmreE and Draco18s for replying my question. I have solved it, I made a collision trigger indeed.
Here is my code after several trials.
if (Input.GetButtonDown ("Fire1") && isCollide)
{
var Cube = GameObject.FindGameObjectsWithTag ("Cube");
if (Cube[0].GetComponent(MeshRenderer).enabled){
var Circle1 = GameObject.FindGameObjectsWithTag ("Circle1");
Circle1[0].GetComponent(MeshRenderer).enabled = true;
Circle1[0].GetComponent(MeshRenderer).material.color = Color.red;
Debug.Log("Muncul");
}
}
function OnTriggerEnter (col : Collider)
{
Debug.Log(isCollide);
if(col.gameObject.name == "Mouse3DSphere")
{
isCollide = true;
}
}
function OnTriggerExit (col : Collider)
{
Debug.Log(isCollide);
if(col.gameObject.name == "Mouse3DSphere")
{
isCollide = false;
}
}
I'm trying to make working keys to my car in my project but when i try to reference another script i get an error saying:
NullReferenceException: Object reference not set to an instance of an object
DrivingScript.Update () (at Assets/Car/Trying To Make Custom Car/DrivingScript.js:21)
I've tried to look it up but couldn't find the problem if you can please help.
var Car : Transform;
var player : Transform;
var exitPoint : Transform;
var tentplayer : Transform;
var campfire : Transform;
var doorTriggerLeft : Transform;
var PlayerCamera : Camera;
var CarCamera : Camera;
var isPlayerVisable : boolean;
private var invScript : Inventory;
function Start () {
invScript = GetComponent(Inventory);
}
function Update (){
if (CarCamera.enabled == false && invScript.LetDrive == true)
{
if (Input.GetKeyDown("r")&& isPlayerVisable){
//Make player invisable and still standing
player.gameObject.SetActiveRecursively(false);
player.gameObject.active = false;
// Parent player to ExitPoint
player.parent = exitPoint.transform;
player.transform.localPosition = Vector3(-1.5,2,0);
//Parent playerParent to car
exitPoint.parent = Car.transform;
exitPoint.transform.localPosition = Vector3(-0.5,2,0);
// Enable car as controllable object
GameObject.Find("CarJeep").GetComponent("Car").enabled = true;
PlayerCamera.enabled = false;
CarCamera.enabled = true;
}
}
else
{
if (CarCamera.enabled == true)
{ if (Input.GetKeyDown("r")){
// Make Character visable again.
player.gameObject.SetActiveRecursively(true);
player.gameObject.active = true;
// PUT CAFTABLE ITEMS HERE\/ \/ \/
campfire.gameObject.SetActiveRecursively(false);
tentplayer.gameObject.SetActiveRecursively(false);
// PUT CRAFTABLE ITEMS HERE ^^^^
// Unparent Player from everything.
player.transform.parent = null;
// Parent Exit Point to Door Trigger.
exitPoint.parent = doorTriggerLeft.transform;
// Disable car as a controllable
GameObject.Find("CarJeep").GetComponent("Car").enabled = false;
PlayerCamera.enabled = true;
CarCamera.enabled = false;
}
}
}
}
function OnTriggerEnter(Player : Collider) {
isPlayerVisable = true;
}
function OnTriggerExit(Player : Collider) {
isPlayerVisable = false;
}
It looks like you didn't set up CarCamera property in the editor and left it null, while this script relies on it being set up.
I'm creating a project for my school and it was going pretty good until now. I've searched for an answer for nearly an hour and still couldn't find anything (wrong tags?).
The thing is that I want to show the name of the item that player is hitting with raycast. I tried this but sadly it's not working:
#pragma strict
var rayLength : int = 10;
private var inventory : Inventory;
private var guiShow : boolean = false;
var bush : GameObject;
var player : GameObject;
function Start()
{
inventory = GameObject.Find("First Person Controller").GetComponent(Inventory);
}
function Update()
{
var hit : RaycastHit;
var forward = transform.TransformDirection(Vector3.forward);
if(Physics.Raycast(transform.position, forward, hit, rayLength))
{
if(hit.collider.gameObject.tag == "Wood")
{
guiShow = true;
if(Input.GetKeyDown("e"))
{
inventory.wood++;
Destroy(hit.collider.gameObject);
guiShow = false;
}
}
else if(hit.collider.gameObject.tag == "Sticks")
{
guiShow = true;
if(Input.GetKeyDown("e"))
{
inventory.stick++;
Destroy(hit.collider.gameObject);
guiShow = false;
}
}
else if(hit.collider.gameObject.tag == "BushFull")
{
guiShow = true;
bush = (hit.collider.gameObject);
if(Input.GetKeyDown("e"))
{
inventory.berry += 5;
bush.GetComponent(BushController).berriesTaken = true;
guiShow = false;
}
}
else
{
guiShow = false;
}
}
else
{
guiShow = false;
}
}
function OnGUI()
{
if(guiShow == true)
{
GUI.Box(Rect(Screen.width / 2, Screen.height / 2, 100, 25), "Pick up" + hit.collider.gameObject);
}
}
If anyone knows answer - please help me. Thanks in advance!
Just use hit.collider.name to retrieve the gameObject's name. If that doesn't work (which I'm 99% sure it will), use hit.collider.gameObject.name
Your code is a little tricky because maybe it would be a greater idea not to use the OnGUI() method. It's easier to call a custom method from update when the raycast hit the player.
One example of an easier implementation is the following:
function Update()
{
var hit : RaycastHit;
var forward = transform.TransformDirection(Vector3.forward);
if(Physics.Raycast(transform.position, forward, hit, rayLength))
{
Debug.Log (hit.collider.gameObject.name); //Shows the hittenGo in the console
drawColliderName(hit.collider.gameObject.name);
if (hit.collider.gameObject.tag == "Woods")
{
//do Woods tuff
}
else if (hit.collider.gameObject.tag == "Sticks")
{
//do Sticks stuff
}
else if (hit.collider.gameObject.tag == "BushFull")
{
//do BushFull stuff
}
}
}
Of course you have to implement the method drawColliderName where you must draw the Collider name on the GUI.
If you just want your code to work, in the OnGUI() you have to call name variable, like in the Debug.Log call of my code, this is just calling hit.collider.gameObject.name instead of hit.collider.gameObject