Upload separate images to each child of a prefab - unity3d

So I think I'm missing a library here. Instead of 'MeshRenderer', I'm using 'MeshRenderer[]' in order to string an array of entries. In short, I'm trying to upload separate images to each child of a prefab. I get the following error message.
using UnityEngine;
using UnityEditor;
using System.IO;
public class WallClick : MonoBehaviour
{
string path;
public MeshRenderer col;
public MeshRenderer[] boxCols;
void OnMouseDown()
{
boxCols = GetComponentsInChildren<MeshRenderer>();
path = EditorUtility.OpenFilePanel("Overwrite with png", "", "png");
GetImage();
}
void EnableChildComponents()
{
foreach (MeshRenderer col in boxCols)
{
col.enabled = true;
}
}
void GetImage()
{
if (path != null)
{
UpdateImage();
}
}
void UpdateImage()
{
byte[] imgByte = File.ReadAllBytes(path);
Texture2D texture = new Texture2D(2, 2);
texture.LoadImage(imgByte);
boxCols.material.mainTexture = texture; //Error here
}
}

boxCols is an array, you need to reference one of the elements in the array, which will be of type MeshRenderer. eg:
boxCols[0].material.mainTexture = texture;

Related

The picture from the unity camera stops coming

My application needs to use the camera (camera from the phone), but when I run it on the phone, a request appears to access the camera. After I click on the consent button, the image does not come. For it to arrive, you need to restart this scene.
I am using this script:
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
using UnityEngine.UI;
using ZXing;
using UnityEngine.SceneManagement;
using Newtonsoft.Json.Linq;
public class QRScanner : MonoBehaviour
{
WebCamTexture webcamTexture;
string QrCode = string.Empty;
void Start()
{
var renderer = GetComponent<RawImage>();
webcamTexture = new WebCamTexture(512, 512);
renderer.material.mainTexture = webcamTexture;
StartCoroutine(GetQRCode());
}
IEnumerator GetQRCode()
{
IBarcodeReader barCodeReader = new BarcodeReader();
webcamTexture.Play();
var snap = new Texture2D(webcamTexture.width, webcamTexture.height, TextureFormat.ARGB32, false);
while (string.IsNullOrEmpty(QrCode))
{
try
{
snap.SetPixels32(webcamTexture.GetPixels32());
var Result = barCodeReader.Decode(snap.GetRawTextureData(), webcamTexture.width, webcamTexture.height, RGBLuminanceSource.BitmapFormat.ARGB32);
if (Result != null)
{
QrCode = Result.Text;
if (!string.IsNullOrEmpty(QrCode))
{
Debug.Log("DECODED TEXT FROM QR: " + QrCode);
var json = JObject.Parse(QrCode);
var Monument = (string) json["Name"];
var City = (string) json["City"];
DataHolders.Monument = Monument;
DataHolders.City = City;
break;
}
}
}
catch (Exception ex) { Debug.LogWarning(ex.Message); }
yield return null;
}
webcamTexture.Stop();
SceneManager.LoadScene(3);
}
}
How can I make the image go after gaining access to the camera?
You need to Ask for permission runtime and once you get the permission you need to call GetQRCode()
On android you could do something like following
private bool hasCameraPermission = false;
WebCamTexture webcamTexture;
string QrCode = string.Empty;
void Start()
{
var renderer = GetComponent<RawImage>();
webcamTexture = new WebCamTexture(512, 512);
renderer.material.mainTexture = webcamTexture;
}
private void Update() {
if (!Permission.HasUserAuthorizedPermission(Permission.Camera)) {
Permission.RequestUserPermission(Permission.Camera);
}
else {
// here you will have camera permission
if (!hasCameraPermission) {
hasCameraPermission = true;
StartCoroutine(GetQRCode());
}
}
}
IEnumerator GetQRCode() {
...
}

Text letter by letter in GO

I'm doing an unity game and I'd like to show text in a panel letter by letter (like if someone was typing).
I've already looked a few things (coroutines,IEnumerator) but didn't figure out how to do it.
My GO is a prefab that I instantiate.I don't instantiate in Scene window, all the instantiations are done in the code. And it't not a MonoBehaviour class.
This is the prefab I instantiate :
InteractionIntro = Instantiate(Resources.Load("Prefab/Play/Interaction") as GameObject);
InteractionIntro.transform.SetParent(canvasGameObject.transform, false);
InteractionIntro.transform.localPosition = new Vector3(0, 200, 0);
public void SetInteractionText(string text)
{
InteractionIntro.GetComponentInChildren<Text>().text = text;
}
The hierarchy looks like this :
So I'd like that the "Text" component has a letter-by-letter effect.
Any idea on how to solve this ?
#UPDATE : maybe adding a script to my prefab ?
#UPDATE : i read the text that's displayed from a file.
#EDIT : so i've created a script. Here's my code:
public class TypingEffect : MonoBehaviour
{
public GameObject GO;
public float delay = 0.1f;
public string fullText;
private string currentText = "";
// Use this for initialization
void Start () {
StartCoroutine(ShowText());
}
IEnumerator ShowText(){
for(int i = 0; i <= fullText.Length; i++){
currentText = fullText.Substring(0,i);
GO.GetComponent<Text>().text = currentText;
yield return new WaitForSeconds(delay);
}
}
}
It works. Text is displayed letter by letter. But its a text I wrote on inspector:
How do I link text to the setInteractionText method ?
#UPDATE : managed to do it, but it only writes letter-by-letter first text, if I display second text it does not work anymore. maybe reset ?
I solved it using a separate script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TypingEffect : MonoBehaviour
{
public GameObject GO;
public float delay = 0.05f;
private string fullText;
private string currentText = "";
// Use this for initialization
void Start () {
StartCoroutine(ShowText());
}
void Update()
{
}
IEnumerator ShowText()
{
currentText="";
for(int i = 0; i <= fullText.Length; i++){
currentText = fullText.Substring(0,i);
GO.GetComponent<Text>().text = currentText;
yield return new WaitForSeconds(delay);
}
}
public void setText(string text)
{
this.fullText = text;
StartCoroutine(ShowText());
}
}
The method setText is called in another class every time I need to set another text. It's important to not forget to call StartCoroutine again.

How do I create entities from an archetype that are renderable

Im playing around with the new DOTS packages.
One thing i have not managed to do is use an archetype to create an entity that is visible in the scene. This is what I have so far, I can see the entities being created in the entity debugger, but they are not rendered. Any help is appreciated. I guess i'm missing some component on the archetype.
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
public class CreateStuff : MonoBehaviour
{
public int CountX = 100;
public int CountY = 100;
void Start()
{
var entityManager = World.Active.EntityManager;
var archetype = entityManager.CreateArchetype(typeof(Translation), typeof(Scale), typeof(Rotation), typeof(MeshRenderer), typeof(MeshFilter));
for (int x = 0; x < CountX; x++)
{
for (int y = 0; y < CountY; y++)
{
var instance = entityManager.CreateEntity(archetype);
var position = transform.TransformPoint(new float3(x - CountX / 2, noise.cnoise(new float2(x, y) * 0.21F) * 10, y - CountY / 2));
entityManager.SetComponentData(instance, new Translation() { Value = position });
entityManager.SetComponentData(instance, new Scale() { Value = 1 });
}
}
}
}
I am not sure if you are still looking for an answer. This is how I managed to get it working.
[SerializeField] private Mesh _mesh;
[SerializeField] private Material _mat;
private void Start()
{
EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
EntityArchetype entityArchetype = entityManager.CreateArchetype(
typeof(RenderMesh),
typeof(LocalToWorld),
typeof(RenderBounds),
);
// create 100 entities
NativeArray<Entity> entityArray = new NativeArray<Entity>(100, Allocator.Temp);
entityManager.CreateEntity(entityArchetype, entityArray);
for (int i = 0; i < entityArray.Length; i++)
{
Entity entity = entityArray[i];
entityManager.SetSharedComponentData(entity, new RenderMesh
{
mesh = _mesh,
material = _mat,
});
}
entityArray.Dispose();
}
I did this by following this tutorial on youtube.
you can use the GameObjectConversionUtility
public GameObject Prefab;
var prefab = Unity.Entities.GameObjectConversionUtility.ConvertGameObjectHierarchy(Prefab, World.Active);
var entityManager = World.Active.EntityManager;
var instance = entityManager.Instantiate(prefab);
And if your Prefab has a renderer it will automagicly have one when it's an entity
If you haven't, do check out the ECS examples: https://github.com/Unity-Technologies/EntityComponentSystemSamples
There is no problem with code itself.
I had same problem and First of all u have to install "Hybrid Renderer" (Windeow=> Package Manager=> Advanced => Show preview pacages => Hybrid Renderer)
My code works fine. You can instantiate objects from entities and prefabs
public class ECSObjectSpawner : MonoBehaviour
{
public static ECSObjectSpawner instance;
private World _defaultWorld;
private EntityManager _entityManager;
public List<FromGameObject> fromGameObjects;
private Dictionary<string, Entity> _convertedFromGo;
public List<FromEntity> fromEntities;
private Dictionary<string, FromEntity> _generatedFromEntity;
private void Awake()
{
instance = instance ?? this;
_convertedFromGo = new Dictionary<string, Entity>();
_generatedFromEntity = fromEntities.ToDictionary(x => x.prefabName, x=>x);
}
void Start()
{
// setup references to World and EntityManager
_defaultWorld = World.DefaultGameObjectInjectionWorld;
_entityManager = _defaultWorld.EntityManager;
GameObjectConversionSettings settings = GameObjectConversionSettings.FromWorld(_defaultWorld, null);
_convertedFromGo = fromGameObjects.ToDictionary(x => x.prefabName, x=> GameObjectConversionUtility.ConvertGameObjectHierarchy(x.gameObjectPrefab, settings));
}
public void Instantiate(string key, float3 position, quaternion rotation)
{
if (_generatedFromEntity.TryGetValue(key, out FromEntity fromEntity))
{
InstantiateFromEnity(position, rotation, fromEntity);
return;
}
if (_convertedFromGo.TryGetValue(key, out Entity entity))
{
InstantiateFromGameObject(position, rotation, entity);
return;
}
}
private void InstantiateFromEnity(float3 position, quaternion rotation, FromEntity fromEntity)
{
EntityArchetype archetype = _entityManager.CreateArchetype(
typeof(Translation),
typeof(Rotation),
typeof(RenderMesh),
typeof(RenderBounds),
typeof(LocalToWorld)
);
Entity myEntity = _entityManager.CreateEntity(archetype);
_entityManager.AddComponentData(myEntity, new Translation
{
Value = position
});
_entityManager.AddComponentData(myEntity, new Rotation
{
Value = rotation
});
_entityManager.AddSharedComponentData(myEntity, new RenderMesh
{
mesh = fromEntity.unitMesh,
material = fromEntity.unitMaterial
});
}
private void InstantiateFromGameObject(float3 position, quaternion rotation, Entity entity)
{
Entity myEntity = _entityManager.Instantiate(entity);
_entityManager.SetComponentData(myEntity, new Translation
{
Value = position
});
_entityManager.SetComponentData(myEntity, new Rotation
{
Value = rotation
});
}
}
[System.Serializable]
public sealed class FromGameObject
{
public string prefabName;
public GameObject gameObjectPrefab;
}
[System.Serializable]
public sealed class FromEntity
{
public string prefabName;
public Mesh unitMesh;
public Material unitMaterial;
}

Reference to a particular Prefab clone

I am developing a simple 2D game. In game, I've created a prefab for charcaters. and I am changing sprite of prefab runtime. This all execute fine. Now I want to apply click event on a particular prefab clone and want to increase scale of prefab. I am attaching a c# script what I have did till now.
public class ShoppingManager : MonoBehaviour {
public static ShoppingManager instance;
[System.Serializable]
public class Shopping
{
public string CharacterName;
public Sprite CharacterSprite;
}
public GameObject CharacterPrefab;
public Transform CharacterSpacer;
public List<Shopping> ShoppingList;
private CharacterScript NewCharacterScript;
/*********************************************Awake()******************************************/
void Awake()
{
MakeSingleton ();
}
/******************************Create object of the script**********************************/
void MakeSingleton()
{
instance = this;
DontDestroyOnLoad (gameObject);
}
// Use this for initialization
void Start () {
LoadCharacters ();
}
void LoadCharacters()
{
foreach (var characters in ShoppingList) {
GameObject NewCharacter = Instantiate (CharacterPrefab) as GameObject;
NewCharacterScript = NewCharacter.GetComponent<CharacterScript> ();
NewCharacterScript.CharacterName = characters.CharacterName;
NewCharacterScript.Charcater.GetComponent<Image> ().sprite = characters.CharacterSprite;
NewCharacterScript.GetComponent<Button> ().onClick.AddListener (() => CharacterClicked (NewCharacterScript.CharacterName, NewCharacterScript.Charcater));
NewCharacter.transform.SetParent (CharacterSpacer, false);
}
}
void CharacterClicked(string CharacterName, GameObject Char)
{
StartCoroutine (IncreaseScale (Char));
}
IEnumerator IncreaseScale(GameObject TempCharacter)
{
int i = 5;
while (i > 0) {
yield return new WaitForSeconds (0.1f);
Vector3 TempVector = TempCharacter.GetComponent<RectTransform> ().localScale;
TempVector.x = TempVector.x + 0.2f;
TempVector.y = TempVector.y + 0.2f;
TempCharacter.GetComponent<RectTransform> ().localScale = TempVector;
i--;
}
}
}
This code triggers click event and also it increases scale but of last clone, not of clicked prefab clone. What I am missing, I can't understand. What should I correct in this. and Yeah! I am also attaching code of a script that I've added on prefab.
public class CharacterScript : MonoBehaviour {
public string CharacterName;
public GameObject Charcater;
}
create collider for your object attach the script below to it this way each object is responsible for handling its own functionalities like increasing its own size
public class characterFunctionalities: MonoBehaviour{
void OnMouseDown()
{
StartCoroutine (IncreaseScale (this.gameobject));
}
IEnumerator IncreaseScale(GameObject TempCharacter)
{
int i = 5;
while (i > 0) {
yield return new WaitForSeconds (0.1f);
Vector3 TempVector = TempCharacter.GetComponent<RectTransform> ().localScale;
TempVector.x = TempVector.x + 0.2f;
TempVector.y = TempVector.y + 0.2f;
TempCharacter.GetComponent<RectTransform> ().localScale = TempVector;
i--;
}
}
}

Sorting Order Not Working Correctly

I am trying to change the order of a sorting layer in unity for a 2D game but the below script isn't working for me:
using UnityEngine;
using System.Collections;
public class LevelManager : MonoBehaviour {
public GameObject player;
public SpriteRenderer deadGuy;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (player.transform.position.y < deadGuy.transform.position.y)
{
deadGuy.sortingOrder = 0;
} else
{
deadGuy.sortingOrder = 2;
}
}
}
The objects have been linked in the inspector window unity before running the game.
EDIT
This is now my code:
using UnityEngine;
using System.Collections;
public class LevelManager : MonoBehaviour {
public GameObject player;
public GameObject deadGuy;
public bool belowTheY;
// Use this for initialization
void Start () {
deadGuy.GetComponent<SpriteRenderer>().sortingOrder = 2;
}
// Update is called once per frame
void Update () {
if (player.transform.localPosition.y < deadGuy.transform.localPosition.y)
{
belowTheY = true;
deadGuy.GetComponent<SpriteRenderer>().sortingOrder = 0;
} else
{
belowTheY = false;
deadGuy.GetComponent<SpriteRenderer>().sortingOrder = 2;
}
}
}
bekowTheY is activating if the user goes below deadGuy's Y position so I know the if statement is executing correctly. However the sorting layer is not being changed
It seems that the player object was on sorting order 0 also, so when the deadGuy object was scripted to go to sorting order 0, it was still showing in front due to taking precedence.