TakePhoto Coroutine doesnt click Picture [duplicate] - unity3d

This question already exists:
Cannot get pixels when webcam is not running
Closed 12 months ago.
I am trying to achieve a picture clicking app in unity and I already made a script, but the TakePhoto Coroutine doesnt seem to work when I press a button, I am using Start and Update functions from this video and TakePhoto Coroutine from this stackoverflow solution. Can someone please help me fix this??
This is my Code:
using UnityEngine;
using System.Collections;
using System.IO;
using UnityEngine.UI;
using System.Collections.Generic;
public class GetCam: MonoBehaviour
{
WebCamTexture webCam;
string your_path = "C:\\Users\\Jay\\Desktop";
public RawImage display;
public AspectRatioFitter fit;
public void Start()
{
webCam = new WebCamTexture();
webCam.Play();
StartCoroutine(TakePhoto());
display.texture = webCam;
}
public void lol(){ //starts the coroutine
StartCoroutine(TakePhoto());
}
public void Update(){
float ratio = (float)webCam.width / (float)webCam.height;
fit.aspectRatio = ratio;
float ScaleY = webCam.videoVerticallyMirrored ? -1f: 1f;
display.rectTransform.localScale = new Vector3(1f,ScaleY, 1f);
int orient = -webCam.videoRotationAngle;
display.rectTransform.localEulerAngles = new Vector3(0,0,orient);
}
IEnumerator TakePhoto() // Start this Coroutine on some button click
{
// NOTE - you almost certainly have to do this here:
yield return new WaitForEndOfFrame();
// it's a rare case where the Unity doco is pretty clear,
// http://docs.unity3d.com/ScriptReference/WaitForEndOfFrame.html
// be sure to scroll down to the SECOND long example on that doco page
Texture2D photo = new Texture2D(webCam.width, webCam.height);
photo.SetPixels(webCam.GetPixels());
photo.Apply();
//Encode to a PNG
byte[] bytes = photo.EncodeToPNG();
//Write out the PNG. Of course you have to substitute your_path for something sensible
File.WriteAllBytes(your_path + "photo.png", bytes);
//lol
}
}

Hi change your start function to something like this:
public void Start()
{
if(WebCamTexture.devices.Length==0)
{
Debug.LogError("can not found any camera!");
return;
}
int index = -1;
for (int i = 0; i < WebCamTexture.devices.Length; i++)
{
if (WebCamTexture.devices[i].name.ToLower().Contains("your webcam name"))
{
Debug.LogError("WebCam Name:" + WebCamTexture.devices[i].name + " Webcam Index:" + i);
index = i;
}
}
if (index == -1)
{
Debug.LogError("can not found your camera name!");
return;
}
WebCamDevice device = WebCamTexture.devices[index];
webCam = new WebCamTexture(device.name);
webCam.Play();
StartCoroutine(TakePhoto());
display.texture = webCam;
}
lien 87:
File.WriteAllBytes(your_path + "photo.png", bytes);
change it to
File.WriteAllBytes(your_path + "\\photo.png", bytes);
an it will be work. good luck.
complete code:
using UnityEngine;
using System.Collections;
using System.IO;
using UnityEngine.UI;
using System.Collections.Generic;
public class GetCam : MonoBehaviour
{
WebCamTexture webCam;
string your_path = "C:\\Users\\Jay\\Desktop";
public RawImage display;
public AspectRatioFitter fit;
public void Start()
{
if(WebCamTexture.devices.Length==0)
{
Debug.LogError("can not found any camera!");
return;
}
int index = -1;
for (int i = 0; i < WebCamTexture.devices.Length; i++)
{
if (WebCamTexture.devices[i].name.ToLower().Contains("your webcam name"))
{
Debug.LogError("WebCam Name:" + WebCamTexture.devices[i].name + " Webcam Index:" + i);
index = i;
}
}
if (index == -1)
{
Debug.LogError("can not found your camera name!");
return;
}
WebCamDevice device = WebCamTexture.devices[index];
webCam = new WebCamTexture(device.name);
webCam.Play();
StartCoroutine(TakePhoto());
display.texture = webCam;
}
public void Update()
{
float ratio = (float)webCam.width / (float)webCam.height;
fit.aspectRatio = ratio;
float ScaleY = webCam.videoVerticallyMirrored ? -1f : 1f;
display.rectTransform.localScale = new Vector3(1f, ScaleY, 1f);
int orient = -webCam.videoRotationAngle;
display.rectTransform.localEulerAngles = new Vector3(0, 0, orient);
}
public void callTakePhoto()
{
StartCoroutine(TakePhoto());
}
IEnumerator TakePhoto() // Start this Coroutine on some button click
{
// NOTE - you almost certainly have to do this here:
yield return new WaitForEndOfFrame();
// it's a rare case where the Unity doco is pretty clear,
// http://docs.unity3d.com/ScriptReference/WaitForEndOfFrame.html
// be sure to scroll down to the SECOND long example on that doco page
Texture2D photo = new Texture2D(webCam.width, webCam.height);
photo.SetPixels(webCam.GetPixels());
photo.Apply();
//Encode to a PNG
byte[] bytes = photo.EncodeToPNG();
//Write out the PNG. Of course you have to substitute your_path for something sensible
File.WriteAllBytes(your_path + "\\photo.png", bytes);
//lol
}
}

Related

I have a problem creating the Unity 2d Platformer game. Why doesn't my code work on a tilemap?

I was making a platform that bounces the player after a certain period of time when the player touches it. I attached this code component to the GameObject, which is a tilemap, and it doesn't work properly. What's wrong with my code? The code and scriptable object are as follows.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ExplosionPlatform : PlatformBase
{
public float explosionPower = 20f;
public float waitTime = 1.5f;
public float colTime = 0f;
public bool isDamageOnce = false;
public Vector2 area = new Vector2(2, 2);
public Vector2 positionModify = new Vector2(1, 0);
private void OnCollisionEnter2D(Collision2D collision)
{
StartCoroutine(Explosion());
}
private IEnumerator Explosion()
{
Debug.Log("ASDF");
yield return new WaitForSeconds(waitTime);
Collider2D[] player = Physics2D.OverlapBoxAll(transform.position + (Vector3)positionModify, area, 0);
foreach (Collider2D col in player)
{
if (col.CompareTag("Player"))
{
col.gameObject.GetComponent<Rigidbody2D>().AddForce(Vector2.up * explosionPower, ForceMode2D.Impulse);
Damage();
isDamageOnce = true;
yield return new WaitForSeconds(3f);
isDamageOnce = false;
}
}
}
private void OnDrawGizmos()
{
Gizmos.color = Color.blue;
Gizmos.DrawWireCube(transform.position + (Vector3)positionModify, area);
}
}
I have confirmed that the code below works properly on GameObject, which is Unity 2d Sprite. Is there any way to use that code while using the tile map?

Cannot get pixels when webcam is not running

I get the following error when I attached coroutine TakePhoto to a button, can someone help?
Error:
Cannot get pixels when webcam is not running
UnityEngine.WebCamTexture:GetPixels ()
GetCam/d__6:MoveNext () (at Assets/GetCam.cs:52)
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)
CodeI took it from
```
using UnityEngine;
using System.Collections;
using System.IO;
using UnityEngine.UI;
public class GetCam: MonoBehaviour
{
WebCamTexture webCam;
string your_path = "C:\\Users\\Jay\\Desktop";
public RawImage display;
public AspectRatioFitter fit;
public void Start()
{
webCam = new WebCamTexture();
webCam.Play();
StartCoroutine(TakePhoto());
display.texture = webCam;
}
public void Update(){
float ratio = (float)webCam.width / (float)webCam.height;
fit.aspectRatio = ratio;
float ScaleY = webCam.videoVerticallyMirrored ? -1f: 1f;
display.rectTransform.localScale = new Vector3(1f,ScaleY, 1f);
int orient = -webCam.videoRotationAngle;
display.rectTransform.localEulerAngles = new Vector3(0,0,orient);
}
IEnumerator TakePhoto() // Start this Coroutine on some button click
{
// NOTE - you almost certainly have to do this here:
yield return new WaitForEndOfFrame();
// it's a rare case where the Unity doco is pretty clear,
// http://docs.unity3d.com/ScriptReference/WaitForEndOfFrame.html
// be sure to scroll down to the SECOND long example on that doco page
Texture2D photo = new Texture2D(webCam.width, webCam.height);
photo.SetPixels(webCam.GetPixels());
photo.Apply();
//Encode to a PNG
byte[] bytes = photo.EncodeToPNG();
//Write out the PNG. Of course you have to substitute your_path for something sensible
File.WriteAllBytes(your_path + "photo.png", bytes);
//lol
}
}

Network Player Direction in Unity

I am currently building my first multiplayer game in unity and having a little bit of an issue changing/transmitting the players direction over the network.
My current player controls class is this:
using UnityEngine;
using System.Collections;
public class playerControls : MonoBehaviour {
#region
//Vars
//Movements Vars
public float runSpeed;
Rigidbody mybody;
Animator myAnimator;
bool playerDirectionE;
#endregion
// Use this for initialization
void Start () {
mybody = GetComponent<Rigidbody>();
myAnimator = GetComponent<Animator>();
playerDirectionE = true;
mybody.transform.eulerAngles = new Vector3(0, 90, 0);
}
// Update is called once per frame
void Update () {
}
void FixedUpdate()
{
float move = Input.GetAxis("Horizontal");
myAnimator.SetFloat("speed", Mathf.Abs(move)); //To intiate the charecter transition(move)
mybody.velocity = new Vector3(move * runSpeed, mybody.velocity.y, 0); //move charecter along the x axis, and keep y on gravity, not touching the z axis
if(move>0 && !playerDirectionE)
{
Flip();
}
else if(move<0 && playerDirectionE)
{
Flip();
}
}
void Flip()
{
playerDirectionE = !playerDirectionE;
Vector3 theScale = transform.localScale;
theScale.z *= -1;
transform.localScale = theScale;
}
}
I am using the following client information to send commands over the network:
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
using System.Collections.Generic;
public class PlayerSyncRotation : NetworkBehaviour {
[SyncVar(hook ="OnPlayerRotSynced")]
private float syncPlayerRotation;
[SerializeField]
private Transform playerTransform;
private float lerpRate = 15;
private float lastPlayerRot;
private float threshold = 1;
private List<float> syncPlayerRotList = new List<float>();
private float closeEneough = 0.3f;
[SerializeField]
private bool userHistoricalInterpolation;
[Client]
void OnPlayerRotSynced(float latestPlayerRotation)
{
syncPlayerRotation = latestPlayerRotation;
syncPlayerRotList.Add(syncPlayerRotation);
}
[Command]
void CmdProvideRotationsToServer(float playerRot)
{
syncPlayerRotation = playerRot;
}
[Client]
void transmitRotations()
{
if (isLocalPlayer)
{
if(CheckIfBeyondThreshold(playerTransform.localScale.z, lastPlayerRot)){
lastPlayerRot = playerTransform.localScale.z;
CmdProvideRotationsToServer(lastPlayerRot);
}
}
}
bool CheckIfBeyondThreshold(float rot1, float rot2)
{
if (Mathf.Abs(rot1 - rot2) > threshold)
{
return true;
}
else
{
return false;
}
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
lerpRotation();
}
void FixedUpdate()
{
transmitRotations();
}
void lerpRotation()
{
if (!isLocalPlayer)
{
HistoricalInterpolation();
}
}
void HistoricalInterpolation(){
if (syncPlayerRotList.Count > 0)
{
LerpPlayerRotation(syncPlayerRotList[0]);
if(Mathf.Abs(playerTransform.localEulerAngles.z - syncPlayerRotList[0]) < closeEneough)
{
syncPlayerRotList.RemoveAt(0);
}
Debug.Log(syncPlayerRotList.Count.ToString() + "syncPlayerRotList Count");
}
}
void LerpPlayerRotation(float rotAngle)
{
Vector3 playerNewRot = new Vector3(0, 0, rotAngle);
playerTransform.rotation = Quaternion.Lerp(playerTransform.rotation, Quaternion.Euler(playerNewRot),lerpRate*Time.deltaTime);
}
}
My rotation looks fine on the client, but over the network on the second client, the rotation is broken and looks very wrong.
I have attached a link to a Webm where you can see the short video snippet of my problem HERE.
Would anyone here have any input as to what I could be doing wrong or how I could fix this issue? any suggestions would be appreciated.
Instead Using your custom code, i will like to say you that use Unet NetworkTransform. It is Unet high level API with different option of customization.
A component to synchronize the position and rotation of networked
objects(more).
Unet HLAPI are open source so you can also get the coding of the networkTransform at bitbucket.

scaling issue on click event

I am developing a 2D game in Unity. I've created a character panel in that to let player select different character. In panel, there are thumbnails for different character. By tapping on a particular character thumbnail, the player can view that character. The original scale of thumbnail is 1, and when player taps on thumbnail, the scale get doubles. All is fine till this. but issue is that whenever player taps on thumbnail its scale gets double. But i want to limit it to once only. I've used flag to stop scaling, But still issue is there. After flag it stops scaling, but now player can click on multiple character simultaneously. I am copying snippet here.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class ViewCharacter : MonoBehaviour {
[SerializeField]
private GameObject TempCharacterHolder ,TempCharacter, TempCharacterText, TempCharacterPrice;
// Use this for initialization
void Start () {
for (int i = 0; i < ShoppingManager.instance.ShoppingList.Count; i++) {
if (i == TheGameController.instance.GetSelectedCharacter ()) {
PlayerPrefs.SetInt ("CharacterScaled" + i, 1);
} else {
PlayerPrefs.SetInt ("CharacterScaled" + i, 0);
}
}
}
public void ViewCharacterFunc()
{
int ClickedCharacter = int.Parse (TempCharacterText.GetComponent<Text> ().text);
foreach (var characters in ShoppingManager.instance.ShoppingList) {
if (string.Equals (characters.CharacterName, TempCharacterText.GetComponent<Text> ().text)) {
if (PlayerPrefs.GetInt("CharacterScaled"+characters.CharacterName)==0) {
ShoppingManager.instance.IncreaseScale (TempCharacter, TempCharacterHolder);
for (int i = 0; i < ShoppingManager.instance.ShoppingList.Count; i++) {
if (i == ClickedCharacter) {
PlayerPrefs.SetInt ("CharacterScaled" + i, 1);
} else {
PlayerPrefs.SetInt ("CharacterScaled" + i, 0);
}
}
}
} else {
Color clr = characters.Character_Holder.GetComponent<Image> ().color;
clr.a = 1;
characters.Character_Holder.GetComponent<Image> ().color = clr;
Vector3 TempVector = characters.CharaacterObject.GetComponent<RectTransform> ().localScale;
TempVector.x = 1f;
TempVector.y = 1f;
characters.CharaacterObject.GetComponent<RectTransform> ().localScale = TempVector;
}
}
}
}
If I understand your question correctly, your characters scale numerous times when you click on them instead of scaling once.
If that's the case, I'd suggest controlling that with a bool:
bool hasTouched = false;
void OnMouseDown()
{
ShoppingManager.instance.Message.SetActive (false);
foreach (var characters in ShoppingManager.instance.ShoppingList) {
Color clr = characters.Character_Holder.GetComponent<Image> ().color;
clr.a = 1;
characters.Character_Holder.GetComponent<Image> ().color = clr;
if (!hasTouched) //if we havent touched
{
Vector3 TempVector = characters.CharaacterObject.GetComponent<RectTransform> ().localScale*Time.deltaTime;
TempVector.x = 1.0f;
TempVector.y = 1.0f;
characters.CharaacterObject.GetComponent<RectTransform> ().localScale = TempVector;
hasTouched = true; //then we scale it, and we have touched it
}
}

Switching active states of two GameObjects in Unity3D

With Unity3D I am trying to create a scene with an alpha texture as a silhouette, which upon looking up is added, then looking down removes.
Currently I have the exposure of an equirectangular image changing on look up, but my silhouette object says I have not assigned it to an instance:
As you can see from the console, it is eventualy recognised, but I cannot set the active state. This is the current state of my code being applied to the scene:
using UnityEngine;
using System.Collections;
public class switchScript : MonoBehaviour {
public Cardboard cb;
public Renderer leftEyeDay;
public Renderer rightEyeDay;
private GameObject[] dayObjects;
public GameObject nightObject;
void Start () {
MeshFilter filter = GetComponent(typeof (MeshFilter)) as MeshFilter;
if (filter != null) {
Mesh mesh = filter.mesh;
Vector3[] normals = mesh.normals;
for (int i=0;i<normals.Length;i++)
normals[i] = -normals[i];
mesh.normals = normals;
for (int m=0;m<mesh.subMeshCount;m++)
{
int[] triangles = mesh.GetTriangles(m);
for (int i=0;i<triangles.Length;i+=3)
{
int temp = triangles[i + 0];
triangles[i + 0] = triangles[i + 1];
triangles[i + 1] = temp;
}
mesh.SetTriangles(triangles, m);
}
}
}
// Update is called once per frame
void Update () {
float xAngle = cb.HeadPose.Orientation.eulerAngles.x;
if (isLookingUp (xAngle)) {
var exposureValue = getExposureValue (xAngle);
leftEyeDay.material.SetFloat ("_Exposure", exposureValue);
rightEyeDay.material.SetFloat ("_Exposure", exposureValue);
toggleNight ();
} else {
leftEyeDay.material.SetFloat ("_Exposure", 1F);
rightEyeDay.material.SetFloat ("_Exposure", 1F);
toggleNight ();
}
}
public bool isLookingUp (float xAngle) {
return xAngle > 270 && xAngle < 340;
}
public float getExposureValue (float xAngle) {
var _xAngle = Mathf.Clamp (xAngle, 320, 340);
return ScaleValue (320.0F, 340.0F, 0.3F, 1.0F, _xAngle);
}
public float ScaleValue (float from1, float to1, float from2, float to2, float v) {
return from2 + (v - from1) * (to2 - from2) / (to1 - from1);
}
void toggleDay() {
print (nightObject);
nightObject = GameObject.FindGameObjectWithTag ("Night");
nightObject.SetActive (false);
}
void toggleNight() {
print (nightObject);
nightObject = GameObject.FindGameObjectWithTag ("Night");
nightObject.SetActive (true);
}
}
GameObject.FindGameObjectWithTag ("Night") returns null when the whole object is set to !active. Just toggle the scripts on that object instead of the whole GO.
Ok, if anyone needs this, this is an easy way to create scene switch:
void Awake() {
silhouetteObject = GameObject.FindGameObjectWithTag ("Night");
silhouetteObject.GetComponent<Renderer>().enabled = false;
}