enter image description here
Since that the Unity Plugin mentioned above display only the Character into the Game Scene when I cliked the button DONE, I am trying to add code into UmazingCC.cs file to display both Character and the Name added in the tab to show both of them in the Game Scene.
The original UmazingCC part code is the following
enter code hereif (GUILayout.Button("Done", bottomBarButtonStyle)){
// Save the character, fade out the camera and load up the game scene
GameObject avatarGO;
if (selectedGender == "Man") {
avatarGO = maleAvatarSpawn;
} else {
avatarGO = femaleAvatarSpawn;
}
var avatar = avatarGO.GetComponent<UMAAvatarBase>();
if( avatar != null )
{
string finalPath = savePath + "/" + characterName + ".txt";
if (finalPath.Length != 0)
{
PersistentNameHolder.characterName = characterName;
var asset = ScriptableObject.CreateInstance<UMATextRecipe>();
asset.Save(avatar.umaData.umaRecipe, avatar.context);
System.IO.File.WriteAllText(finalPath, asset.recipeString);
ScriptableObject.Destroy(asset);
// If the camera has a fader, make it fade out and load the game scene, otherwise just load the scene ourselves
if (orbitCamera.GetComponent<CameraFader>() != null) {
orbitCamera.GetComponent<CameraFader>().fadeOutAndLoadScene(gameSceneName);
} else {
Application.LoadLevel(gameSceneName);
}
The Name metod code is the following
enter code here void FinishWindowContents (int windowID) {
GUILayout.BeginHorizontal(horizontalLayoutStyle);
GUILayout.BeginVertical(verticalLayoutStyle);
GUILayout.Label ("Nombre", bottomBarLabelStyle);
characterName = GUILayout.TextField(characterName);
GUILayout.EndVertical();
GUILayout.BeginVertical(verticalLayoutStyle);
if (characterName.Length == 0) {
GUI.enabled = false;
}
For it, Could anybody say me what code lines should I add in this place to show both Character and its name in the Game Scene?
Thanks in advance and sorry for my little english.
Ps. I added a screen image to see better the problem.
Related
I'm using Screenshot code to take a screenshot of the screen which is working fine but its also taking the arcore models with it. Is there a way to take a screenshot before models are rendered?
I tried to SetActive(false) then take a screenshot then SetActive(true), it does work but there's a noticeable difference i.e. model disappears than reappears.
Update: This is a script applied on ScreenShotCamera and it is updated after removing all the bugs (thanks to #Shingo), feel free to use it it's working properly
using GoogleARCore;
using OpenCVForUnitySample;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
[RequireComponent(typeof(Camera))]
public class SnapshotCamera : MonoBehaviour
{
Camera snapCam;
public UnityEngine.UI.Text text;
public RenderTexture mRenderTexture;
int resWidth=480;
int resHeight=800;
// Start is called before the first frame update
public void initialize(ARBackgroundRenderer background, Material material)
{
background = new ARBackgroundRenderer();
snapCam = GetComponent<Camera>();
background.backgroundMaterial = material;
background.camera = snapCam;
background.mode = ARRenderMode.MaterialAsBackground;
if (snapCam.targetTexture == null)
{
snapCam.targetTexture = new RenderTexture(resWidth, resHeight, 24);
}
else
{
snapCam.targetTexture.height = resHeight;
snapCam.targetTexture.width = resWidth;
//resHeight = snapCam.targetTexture.height;
//resWidth = snapCam.targetTexture.width;
}
background.camera.cullingMask = LayerMask.NameToLayer("Default");
//snapCam.CopyFrom(background.camera);
snapCam.gameObject.SetActive(false);
}
public void TakeSnapShot()
{
snapCam.gameObject.SetActive(true);
}
void LateUpdate()
{
if (snapCam.gameObject.activeInHierarchy)
{
snapCam.cullingMask = LayerMask.NameToLayer("Default");
if (ARCoreBackgroundRenderer.screenShot == null)
ARCoreBackgroundRenderer.screenShot = new Texture2D(resWidth, resHeight, TextureFormat.RGB24, false);
snapCam.Render();
RenderTexture.active = snapCam.targetTexture;
ARCoreBackgroundRenderer.screenShot.ReadPixels(new Rect(0, 0, resWidth, resHeight), 0, 0);
ARCoreBackgroundRenderer.screenShot.Apply();
snapCam.gameObject.SetActive(false);
HandPoseRecognition.captureTexture = false;
//string name = string.Format("{0}_Capture{1}_{2}.png", Application.productName, "{0}", System.DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"));
//UnityEngine.Debug.Log("Permission result: " + NativeGallery.SaveImageToGallery(ARCoreBackgroundRenderer.screenShot, Application.productName + " Captures", name));
}
}
}
Perhaps I was a little ambiguous, what u mentioned in the comment has already been resolved thanks to you but the problem now is.
I'll show you the images:
These are the 2 cameras I have:
This is what my Main (ARCore Camera) shows
And this is what the (ScreenShot Camera) Shows
You can use layer, put every arcore models in one layer (eg. ARLAYER), then set camera's culling mask to avoid these models.
Pseudo code:
// Set models' layer
foreach (GameObject arcoreModel in arcoreModels)
arcoreModel.layer = ARLAYER;
// Set camera's culling mask
camera.cullingMask = ~(1 << ARLAYER);
camera.Render();
Create screenshot camera from another camera
var go = new GameObject("screenshotcamera");
// Copy transform
go.transform.position = mainCamera.transform.position.
...
// Copy camera
var screenshotcamera= go.AddComopnent<Camera>();
screenshotcamera.CopyFrom(mainCamera);
Update with your script
snapCam = GetComponent<Camera>();
I'm trying to create a modification to the ARCore sample Andy placement app by only rendering a single plane instead of all the detected planes. I'd like to achieve this by tapping on the plane to be rendered. Here's what I've tried.
protected override void OnEndManipulation(TapGesture gesture)
{
if (gesture.WasCancelled)
{
return;
}
// If gesture is targeting an existing object we are done.
if (gesture.TargetObject != null)
{
return;
}
// Raycast against the location the player touched to search for planes.
TrackableHit hit;
TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinInfinity | TrackableHitFlags.PlaneWithinPolygon;
if (Frame.Raycast(gesture.StartPosition.x, gesture.StartPosition.y, raycastFilter, out hit))
{
Debug.Log("Entered into hit if condition");
// Use hit pose and camera pose to check if hittest is from the
// back of the plane, if it is, no need to create the anchor.
if ((hit.Trackable is DetectedPlane) &&
Vector3.Dot(FirstPersonCamera.transform.position - hit.Pose.position,
hit.Pose.rotation * Vector3.up) < 0)
{
//var andyObject = Instantiate(AndyPrefab, hit.Pose.position, hit.Pose.rotation);
Debug.Log("Hit at back of the current DetectedPlane");
}
else
{
if (PlaneFixed is false)
{
foreach (GameObject plane in DetectedPlaneGenerator.instance.PLANES) //RK
{
// THE PROBLEM IS HERE! HOW TO GET CORRECT TYPECAST?
if (hit.Trackable is plane)
{
Debug.Log("Plane Selected");
PlaneFixed = true;
FixPositionButton.gameObject.SetActive(true);
}
else
{
plane.SetActive(false);
}
}
}
}
}
}
The problem is that I'm unable to get the correct matching between a GameObject (PLANES - created in DetectedPlaneGenerator.cs) and the DetectedPlane object (return by hit.Trackable, using the PlaneWithinInfinity | PlaneWithinPolygon raycastfilters).
I've also seen the method to try and associate a 'tag' to the DetectedPlaneVisualizer (solution to this). However, I see that this too deals with planes using a GameObject. How to match the GameObject and Hit.Trackable (DetectedPlane Object) to identify which specific plane was just tapped on?
I'm currently making a quiz game that has three buttons, from an object pool, and I want them to turn green or red depending on whether or not they are the correct answer. This works perfectly.
When I add the coRoutine to change the button back to clear so the next question can be answered, the button almost never changes color after clicking and essentially nothing happens. Would really appreciate any help!! Thank you.
public void HandelClick()
{
var colors = GetComponent<Button> ().colors;
if( ! answerData.isCorrect)
{
colors.normalColor = Color.red;
GetComponent<Button>().colors = colors;
}
else
{
colors.normalColor = Color.green;
GetComponent<Button> ().colors = colors;
playerMovement.dodge();
}
StartCoroutine("Revert");
//gameController.AnswerButtonClicked(answerData.isCorrect);
}
IEnumerator Revert()
{
Debug.Log(" we are reverting " + Time.time);
yield return new WaitForSeconds(1.8f);
Debug.Log(" we are reverting again " + Time.time);
var colors = GetComponent<Button> ().colors;
colors.normalColor = Color.clear;
GetComponent<Button> ().colors = colors;
gameController.AnswerButtonClicked(answerData.isCorrect);
}
Changing the colors works as you said (you can see that in the Inspector of the Button)
The problem is that the Image component's color doesn't get updated automatically since the Button isn't receiving any pointer event like PointerDown, PointerExit etc => the new color is not applied to the Image (only in the cases where you do a new pointer event like enter, exit, up or down).
You could solve this by doing
GetComponent<Image>().color = colors.normalColor;
additional everywhere you change it.
Note: In general you should use GetComponent only once in Awake
private Button _button;
private Image _image;
private void Awake()
{
_button = GetComponent<Button>();
_image = GetComponent<Image>();
}
and than reuse the references _image and _button
I am making a scene game with a Character Avatar and its name (The interface has a text field to add in it its name) and then when I clicked the DONE button, I want to run a new scene to display both Character Avatar and the name added into text field, for it, Could anybody help me to make the code to do it? Thanks in advance Alejandro Castan Ps. Sorry for my little English and hope you can understand me
void FinishWindowContents (int windowID) {
GUILayout.BeginHorizontal(horizontalLayoutStyle);
GUILayout.BeginVertical(verticalLayoutStyle);
GUILayout.Label ("Name", bottomBarLabelStyle);
characterName = GUILayout.TextField(characterName);
GUILayout.EndVertical();
GUILayout.BeginVertical(verticalLayoutStyle);
if (characterName.Length == 0) {
GUI.enabled = false;
}
if (GUILayout.Button("Done", bottomBarButtonStyle)) {
// Save the character, fade out the camera and load up the game scene
GameObject avatarGO;
if (selectedGender == "Man") {
avatarGO = maleAvatarSpawn;
} else {
avatarGO = femaleAvatarSpawn;
}
var avatar = avatarGO.GetComponent<UMAAvatarBase>();
if( avatar != null )
{
string finalPath = savePath + "/" + characterName + ".txt";
if (finalPath.Length != 0)
{
PersistentNameHolder.characterName = characterName;
var asset = ScriptableObject.CreateInstance<UMATextRecipe>();
asset.Save(avatar.umaData.umaRecipe, avatar.context);
System.IO.File.WriteAllText(finalPath, asset.recipeString);
ScriptableObject.Destroy(asset);
// If the camera has a fader, make it fade out and load the game scene, otherwise just load the scene ourselves
if (orbitCamera.GetComponent<CameraFader>() != null) {
orbitCamera.GetComponent<CameraFader>().fadeOutAndLoadScene(gameSceneName);
} else {
Application.LoadLevel(gameSceneName);
}
}
}
}
if (characterName.Length == 0) {
GUI.enabled = true;
}
GUILayout.EndVertical();
GUILayout.EndVertical();
}
Note-I added some code(this code is more complex that I asked above) you can see it. This code is from Unity plugin and what I would need to add only the text added in the text field into the new scene when I do click in the Done button.
PlayerPrefs is a way to save data between scenes.
It doesn't need some extra code and is great for what you are doing because it allows you to write/read in any moment of your game.
Hope you'll find useful.
I am working on an Unity3d project in which I want to dynamically add 3d objects to the scene, at the same position, orientation, upon a keyPress. For doing so, I imported these objects and made a prefab for all of these.. I am using the following script to do so.. bt it doesn't do the needfull.. The new object gets instantiated and gets added to the scene but the old objects don't get destroyed. And also ,the position of the new objects is not always the same. The scene consists of a Cube initially. After I press '1' ,'2' etc .. I want a new Object to replace the 1 being displayed (at the same position).
script :
var myCar : GameObject;
var Cube : GameObject;
var Globe: GameObject;
var Clock : GameObject;
var Pistol : GameObject;
var LCD : GameObject;
var prev : int;
var temp: GameObject;
function Start ()
{
prev =0;
temp=null;
}
function Update ()
{
if(prev==0)
temp=Cube;
else if(prev==1)
temp=myCar;
else if(prev==2)
temp=Globe;
else if(prev==3)
temp=Pistol;
else if(prev==4)
temp=Clock;
else if(prev==5)
temp=LCD;
if(Input.GetKey(KeyCode.Alpha1 || KeyCode.Keypad1))
{
if(prev!=1)
{
Instantiate(myCar,temp.transform.position ,temp.transform.rotation);
myCar.transform.localScale = Vector3(0.06,0.06,0.06);
Destroy(temp);
prev=1;
}
}
else if(Input.GetKey(KeyCode.Alpha2 || KeyCode.Keypad2))
{
if(prev!=2)
{
Instantiate(Globe,temp.transform.position ,temp.transform.rotation);
Globe.transform.localScale = Vector3(0.04,0.04,0.04);
Destroy(temp);
prev=2;
}
}
else if(Input.GetKey(KeyCode.Alpha3 || KeyCode.Keypad3))
{
if(prev!=3)
{
Instantiate(Pistol,temp.transform.position ,temp.transform.rotation);
Pistol.transform.localScale = Vector3(0.03,0.03,0.03);
Destroy(temp);
prev =3;
}
}
else if(Input.GetKey(KeyCode.Alpha4 || KeyCode.Keypad4))
{
if(prev!=4)
{
Instantiate(Clock,temp.transform.position ,temp.transform.rotation);
Clock.transform.localScale = Vector3(0.08,0.08,0.08);
Destroy(temp);
prev=4;
}
}
else if(Input.GetKey(KeyCode.Alpha5 || KeyCode.Keypad5))
{
if(prev!=5)
{
Instantiate(LCD,temp.transform.position ,temp.transform.rotation);
LCD.transform.localScale = Vector3(0.04,0.04,0.04);
Destroy(temp);
prev=5;
}
}
}
There are several things to consider:
It would be better to store a reference to the currently active object intead of the if-else-if part.
Destroy is called on the prefab objects but not on the existing GameObject instance and thus doesn't do anything.
The same for all manipulations of transform. They affect the prefabs only.
Not really a bug but really an enhancement: Scale your models in our 3D software so that they can be instantiated without localScale adjusting.
UPDATE: If you don't have access to the original models of the 3D software like Blender, Maya, ... you can easily define the appropriate scale in the prefab. The keypoint is to minimise repeating stuff in your code and to put all kind of property settings into the prefab.
Putting this altogether, my suggestions:
Refine your original models like in 4.
Introduce a member variable to store a reference to the current object.
UPDATE: If you want a special object for example Cube initialised on start, you first drag it into the scene, and then drag the newly created Cube from hierarchy view to the varable current. So you see the cube first when starting the scene and your script knows that this is current when it has to replace it.
Create a method for object instantiation
I'm working in C# but it should be something like
var current : GameObject;
...
function ReplaceObject (prefab : GameObject, newKey : int) {
if (newKey != prev) {
GameObject newObject = Instantiate(prefab, current.transform.position,
current.transform.rotation);
Destroy(current);
current = newObject;
prev = newKey;
}
}
...
function Update ()
{
if(Input.GetKey(KeyCode.Alpha1 || KeyCode.Keypad1)) {
ReplaceObject (myCar, 1);
} else if(Input.GetKey(KeyCode.Alpha2 || KeyCode.Keypad2))
ReplaceObject (Globe, 2);