How to Display WebcamTexture as Full Screen on Android Portrait Mode? - unity3d

I am trying to display full screen Webcamtexture on android Portrait mode.
but when i am building and testing it on my device its rotated and videoRotationAngle is 90
I am using RawImage as a texture. I have seen on some post that you have to rotate the transform and get the right angle. But the problem is that if I rotate RawImage UI it will no longer full screen view.
var camImage:UnityEngine.UI.RawImage;
var baseRotation:Quaternion;
var webcamTexture:WebCamTexture;
var rotation:UnityEngine.UI.Text;
function Start () {
webcamTexture = new WebCamTexture(Screen.width,Screen.height);
camImage.texture=webcamTexture;
camImage.material.mainTexture = webcamTexture;
webcamTexture.Play();
rotation.text= webcamTexture.videoRotationAngle.ToString(); // to check the angle
}

I know this is late reply but may help someone facing similar issues.
If you are using RawImage as a Texture, below code should help you achieve the rendering both in Potrait and Landscape mode.
Just ensure that you set "Aspect Mode" in "Aspect Ratio Fitter" of Raw Image to "Width Controls Height" or "Height Controls Width" (whichever is larger based on orientation)
Code Snippet
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
using System.Collections;
public class DeviceCameraController : MonoBehaviour
{
public RawImage image;
public AspectRatioFitter imageFitter;
//set it to either FRONT or BACK
string myCamera = "BACK";
// Device cameras
WebCamDevice frontCameraDevice;
WebCamDevice backCameraDevice;
WebCamDevice activeCameraDevice;
WebCamTexture frontCameraTexture;
WebCamTexture backCameraTexture;
WebCamTexture activeCameraTexture;
// Image rotation
Vector3 rotationVector = new Vector3(0f, 0f, 0f);
// Image uvRect
Rect defaultRect = new Rect(0f, 0f, 1f, 1f);
Rect fixedRect = new Rect(0f, 1f, 1f, -1f);
// Image Parent's scale
Vector3 defaultScale = new Vector3(1f, 1f, 1f);
Vector3 fixedScale = new Vector3(-1f, 1f, 1f);
void Start()
{
// Check for device cameras
if (WebCamTexture.devices.Length == 0)
{
Debug.Log("No devices cameras found");
return;
}
// Get the device's cameras and create WebCamTextures with them
frontCameraDevice = WebCamTexture.devices.Last();
backCameraDevice = WebCamTexture.devices.First();
frontCameraTexture = new WebCamTexture(frontCameraDevice.name);
backCameraTexture = new WebCamTexture(backCameraDevice.name);
// Set camera filter modes for a smoother looking image
frontCameraTexture.filterMode = FilterMode.Trilinear;
backCameraTexture.filterMode = FilterMode.Trilinear;
// Set the camera to use by default
if (myCamera.Equals("FRONT"))
SetActiveCamera(frontCameraTexture);
else if (myCamera.Equals("BACK"))
SetActiveCamera(backCameraTexture);
else // default back
SetActiveCamera(backCameraTexture);
}
// Set the device camera to use and start it
public void SetActiveCamera(WebCamTexture cameraToUse)
{
if (activeCameraTexture != null)
{
activeCameraTexture.Stop();
}
activeCameraTexture = cameraToUse;
activeCameraDevice = WebCamTexture.devices.FirstOrDefault(device =>
device.name == cameraToUse.deviceName);
image.texture = activeCameraTexture;
image.material.mainTexture = activeCameraTexture;
activeCameraTexture.Play();
}
// Make adjustments to image every frame to be safe, since Unity isn't
// guaranteed to report correct data as soon as device camera is started
void Update()
{
// Skip making adjustment for incorrect camera data
if (activeCameraTexture.width < 100)
{
Debug.Log("Still waiting another frame for correct info...");
return;
}
// Rotate image to show correct orientation
rotationVector.z = -activeCameraTexture.videoRotationAngle;
image.rectTransform.localEulerAngles = rotationVector;
// Set AspectRatioFitter's ratio
float videoRatio =
(float)activeCameraTexture.width / (float)activeCameraTexture.height;
imageFitter.aspectRatio = videoRatio;
// Unflip if vertically flipped
image.uvRect =
activeCameraTexture.videoVerticallyMirrored ? fixedRect : defaultRect;
}
}
Let me know if you face any issue.

Well you have two options: you could either pick portrait or landscape and block screen rotation, or you could automatically rotate your object and stretch it according to the screen boundaries. See Screen.height and Screen.length for more info.

(mCamera.videoRotationAngle + 90) % 360 will rotate the texture properly, then assign a localScale that swaps the height and width of the texture to fix the size.

You need to flip and rotate it. If you something like CameraCaptureKit (https://www.assetstore.unity3d.com/en/#!/content/56673) you will see there is diffirent ways of achieving what you want. In CameraCaptureKit there is a customized RawImage component that essentailly fiddles with the UV coordinates of the RawImahge instead of roatting it. That way you can rotate the image 90 or 270 and flip it without worring if the phone is running in landscape mode or what ever.

Related

Canvas rotating when I change it to worldSpace, Unity

I've got a canvas that changes from Overlay to worldSpace when an event occurs, but when it changes to Overlay from worldSpace, the rotation of the canvas is changed, which I don't want it to be.
Images:
As you can see in the order that the images are, it starts with no rotation in worldSpace, then the event occurs changes it to overlay and the rotation is now 140, after the event and I'm back in worldSpace, it is still 140 degrees.
I don't know what is wrong with this. Please help if you can
This happens because, internally, the Canvas is being transformed into camera space when set to Overlay. That's how it renders. Your solution would be to cache the transform before changing the Render Mode.
Something like this, given a component:
using UnityEngine;
[RequireComponent(typeof(Canvas))]
public class CanvasRenderModeSwitcher : MonoBehaviour
{
private Canvas canvas;
private Vector3 position;
private Vector3 scale;
private Quaternion rotation;
private void OnEnable()
{
canvas = GetComponent<Canvas>();
}
public void SetRenderMode(RenderMode renderMode)
{
if (renderMode == RenderMode.WorldSpace)
{
// Set the render mode before values are reset.
canvas.renderMode = renderMode;
// Restore the values.
transform.position = position;
transform.rotation = rotation;
transform.localScale = scale;
}
else
{
// Cache the values.
position = transform.position;
rotation = transform.rotation;
scale = transform.localScale;
// Set the render mode after values are cached.
canvas.renderMode = renderMode;
}
}
}

Why can't I zoom my Unity2D Orthographic game?

I've watched several videos and read posts that indicate I should be able to zoom the camera view during my game by changing the Size parameter for the MainCamera (Unity 2D game, orthographic projection). Doing so zooms the Scene View in and out, but nothing I change anywhere in the Inspector changes the Game view.
Can anyone advise? Thanks.
The orthographic size defines the viewing volume of the camera and it will only zoom on the elements rendered by it. It looks like you are trying to zoom on a Canvas, but UI elements are rendered on top of the whole scene.
In order to zoom in and out you can either:
set the Canvas Render Mode to World Space and then place it in front of the camera
use a script that lets you zoom in on a canvas, have a look here: Pinch zoom on UI
public class PinchZoom : MonoBehaviour
{
public Canvas canvas; // The canvas
public float zoomSpeed = 0.5f; // The rate of change of the canvas scale factor
void Update()
{
// If there are two touches on the device...
if (Input.touchCount == 2)
{
// Store both touches.
Touch touchZero = Input.GetTouch(0);
Touch touchOne = Input.GetTouch(1);
// Find the position in the previous frame of each touch.
Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition;
Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition;
// Find the magnitude of the vector (the distance) between the touches in each frame.
float prevTouchDeltaMag = (touchZeroPrevPos - touchOnePrevPos).magnitude;
float touchDeltaMag = (touchZero.position - touchOne.position).magnitude;
// Find the difference in the distances between each frame.
float deltaMagnitudeDiff = prevTouchDeltaMag - touchDeltaMag;
// ... change the canvas size based on the change in distance between the touches.
canvas.scaleFactor -= deltaMagnitudeDiff * zoomSpeed;
// Make sure the canvas size never drops below 0.1
canvas.scaleFactor = Mathf.Max(canvas.scaleFactor, 0.1f);
}
}
}
I hope this will help you!

Calling my background Sprite to fill screen in Unity

I know that there are many questions like this on the net but I haven't found a solution to my problem yet...
I'm trying to make a background image that fills the screen. In my game, there is a canvas and inside this Canvas there is a gameObject which has attached the sprite component.
Many solutions includes this code:
void Awake()
{
SpriteRenderer sr = GetComponent<SpriteRenderer>();
if (sr == null) return;
transform.localScale = new Vector3(1, 1, 1);
float width = sr.sprite.bounds.size.x;
float height = sr.sprite.bounds.size.y;
double variable = Camera.main.orthographicSize * 4.0;
float worldScreenHeight = (float)variable;
float worldScreenWidth = worldScreenHeight / Screen.height * Screen.width;
transform.localScale = new Vector2(worldScreenWidth / width, worldScreenHeight / height);
}
But I tried it and it makes the gameobject really small.
Any ideas?
At first, select your Canvas game object. in Canvas Scaler component set UI Scale Mode to Constant Pixel Size.
Note that, when you set UI Scale Mode to Scale With Screen Size, your image changes by screen width or height.
Also, Note that your image should be in the center of its parent. Set the transform position and rotation of your image to this:
Now Change your code to this:
void Awake()
{
SpriteRenderer sr = GetComponent<SpriteRenderer>();
if (sr == null) return;
transform.localScale = new Vector3(1, 1, 1);
float width = sr.sprite.bounds.size.x;
float height = sr.sprite.bounds.size.y;
transform.localScale = new Vector2(Screen.width / width, Screen.height / height);
}
Hope it helps you.

Maintain proportion of a sprite in Unity

I added a sprite with a PNG image to a 16:9 scene in Unity. When I view the scene on the iPad (4:3 aspect ratio) it appears distorted. How can I make the sprite maintain it's proportion?
The image on the iPad:
On the computer (in Unity):
Here are my settings.
I tried using this script for the camera but it didn't work it just enlarges the character and it was still distorted. (source):
using UnityEngine;
public class PixelPerfectCamera : MonoBehaviour {
public float pixelsToUnits = 100;
private Camera camera;
void Awake () {
camera = Camera.main;
}
void Update () {
camera.orthographicSize = Screen.height / pixelsToUnits / 2;
}
}
I am using the sprite in a 2D scene using Unity 5.
You can use preserve aspect option of the image.
You are using the sprite on a UI/Image which requires a rect transform component resulting it resize according to screen. Use sprite renderer on empty object.
One way to create this is using menu:
GameObject->2D Object->Sprite
Hope this helps

How can I move an UI Image to a touch position?

I have an image on the scene. Now when I touch on my mobile device to a specific position, I want, that the image moves to this position.
How can I do it?
I wrote this:
transform.position = Input.mousePosition;
But this don't work. Ok, it's working, but the image is not anymore on the screen. It's somewhere on the right side.
I found this. But it's also not working:
gameObject.GetComponent<RectTransform>().localPosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
Here is the problem, that when I touch on the screen bottom left (mobile) the object is in the center of the screen.
You can move the UI Image by putting the following in a script attached to it:
void Update() {
for (var i = 0; i < Input.touchCount; i++) {
if (Input.GetTouch(i).phase == TouchPhase.Began) {
// assign new position to where finger was pressed
transform.position = new Vector3 (Input.GetTouch(i).position.x Input.GetTouch(i).position.y, transform.position.z);
}
}
}
use
gameobject.transform.position = camera.ScreenToWorldPoint(Input.mousePosition);
for Desktop. for mobile you want to replace InputmousePostion with input.getTouch[i].position.
I know this is an old post but this took way longer than it should have so thought i'd share my solution in case it helps other trying to do the same thing.
var touchpoint = Instantiate(Resources.Load("prefabs/touchpoint"), new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
//set it parent to the main canvas
touchpoint.transform.parent = MainCanvas.transform;
//convert touch position to localposition reletive to canvas
Vector2 localPos;
RectTransformUtility.ScreenPointToLocalPointInRectangle(MainCanvasRect, new Vector3(t.position.x, t.position.y, 0), null, out localPos);
//set position on canvas
touchpoint.transform.localPosition = localPos;