I have some TV model, like
and C# code
using UnityEngine;
using System.Collections;
public class ClicktoPlayWebMovieClass : MonoBehaviour {
// Use this for initialization
void Start () {
}
private Vector3 FindBoundCord (int i, GameObject _GameObject){
/*This is basically where the code starts. It starts out by creating a
* bounding box around the target GameObject.
It calculates the 8 coordinates forming the bounding box, and
returns them all to the for loop.
Because there are no real method which returns the coordinates
from the bounding box I had to create a switch/case which utillized
Bounds.center and Bounds.extents.*/
Bounds _TargetBounds = _GameObject.GetComponent<Renderer>().bounds;
Vector3 _TargetCenter = _TargetBounds.center;
Vector3 _TargetExtents = _TargetBounds.extents;
switch(i){
case 0:
return _TargetCenter + new Vector3(_TargetExtents.x, _TargetExtents.y, _TargetExtents.z);
case 1:
return _TargetCenter + new Vector3(_TargetExtents.x, _TargetExtents.y, _TargetExtents.z*-1);
case 2:
return _TargetCenter + new Vector3(_TargetExtents.x, _TargetExtents.y*-1, _TargetExtents.z);
case 3:
return _TargetCenter + new Vector3(_TargetExtents.x, _TargetExtents.y*-1, _TargetExtents.z*-1);
case 4:
return _TargetCenter + new Vector3(_TargetExtents.x*-1, _TargetExtents.y, _TargetExtents.z);
case 5:
return _TargetCenter + new Vector3(_TargetExtents.x*-1, _TargetExtents.y, _TargetExtents.z*-1);
case 6:
return _TargetCenter + new Vector3(_TargetExtents.x*-1, _TargetExtents.y*-1, _TargetExtents.z);
case 7:
return _TargetCenter + new Vector3(_TargetExtents.x*-1, _TargetExtents.y*-1, _TargetExtents.z*-1);
default:
return Vector3.zero;
}
}
IEnumerator MyMethod() {
//Debug.Log("Before Waiting 2 seconds");
yield return new WaitForSeconds(2);
//Debug.Log("After Waiting 2 Seconds");
}
public string url = "http://becunningandfulloftricks.files.wordpress.com/2013/04/hedgehog_in_the_fog.ogg";
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown (0)) {
Debug.Log("clicked");
// Start download
var www = new WWW(url);
// Make sure the movie is ready to start before we start playing
var movieTexture = www.movie;
while (!movieTexture.isReadyToPlay) {
StartCoroutine(MyMethod());
}
print("LOADED!!!");
Vector2 _ObjectScreenCord, _Xmin = new Vector2(Screen.width,0), _Xmax = Vector2.zero, _Ymin = new Vector2(Screen.height,0), _Ymax = Vector2.zero;
float _Height, _Width;
for(int i = 0; i != 8; i++){
//FindBoundCord() locates the eight coordinates that forms the boundries, followed by converting the coordinates to screen space.
// The entire script starts in FindBoundCord
_ObjectScreenCord = Camera.main.WorldToScreenPoint(FindBoundCord(i, transform.gameObject));
/* After gathering the coordinates and converting them to screen space
we try to locate which of these have the highest/minimum x and y values.
The difference between highest/minimum x and y must correspond to
width and height.*/
if(_ObjectScreenCord.x > _Xmax.x){
_Xmax.x = _ObjectScreenCord.x;
}
else if(_ObjectScreenCord.x < _Xmin.x){
_Xmin.x = _ObjectScreenCord.x;
}
if(_ObjectScreenCord.y > _Ymax.x){
_Ymax.x = _ObjectScreenCord.y;
}
else if(_ObjectScreenCord.y < _Ymin.x){
_Ymin.x = _ObjectScreenCord.y;
}
}
//Too measure the distance between them, I use the Vector2 method Distance.
_Height = Vector2.Distance(_Ymax, _Ymin);
if (_Height > Screen.height || _Height < 0){
_Height = 0;
}
_Width = Vector2.Distance(_Xmax, _Xmin);
if (_Width > Screen.width || _Width < 0){
_Width = 0;
}
print(_Height+" - "+_Width);
GetComponent<Renderer>().material.mainTexture = movieTexture;
// Assign clip to audio source
// Sync playback with audio
GetComponent<AudioSource>().clip = movieTexture.audioClip;
// Play both movie & sound
GUITexture gt = GetComponent<GUITexture>();
gt.texture = movieTexture;
transform.localScale = new Vector3 (0f,0f,0f);
transform.position = new Vector3 (0.5f,0.5f,0f);
Rect r = gt.pixelInset;
print(_Width);
print(movieTexture.width / 2);
r.xMin = -_Width / 2;
r.xMax = _Width / 2;
r.yMin = -_Height / 2;
r.yMax = _Height / 2;
// r.xMin = -movieTexture.width / 2;
// r.xMax = movieTexture.width / 2;
// r.yMin = -movieTexture.height / 2;
// r.yMax = movieTexture.height / 2;
gt.pixelInset=r;
movieTexture.Play();
GetComponent<AudioSource>().Play();
}
}
}
When I'am clicking on my TV set, looks good:
It looks good until I am not rotate my camera. After camera rotation movieTexture has initial position on the screen:
and it makes my TV set broken...
How to specify movieTexture, that it must have position of the GetComponent<Renderer>().material.mainTexture? I need make to look something like this
But instead of screen of the TV must be video of the movieTexture at it must rotate, like screen of the TV set...
Have you looked at projectors? They do this pretty well and just changes the texture like you want. They are normally used for shadows but any texture can be projected on any model.
http://docs.unity3d.com/Manual/class-Projector.html
Related
I'm trying to implement bounce physics on a ball in my game using MonoGame c#. I've googled plenty but I'm unable to understand how to do this.
The circle should be able to hit any of the red lines and bounce realistically (not just invert the velocity).
I'm using this code to detect collision:
public bool IntersectCircle(Vector2 pos, float radius, out Vector2 circleWhenHit)
{
circleWhenHit = default;
// find the closest point on the line segment to the center of the circle
var line = End - Start;
var lineLength = line.Length();
var lineNorm = (1 / lineLength) * line;
var segmentToCircle = pos - Start;
var closestPointOnSegment = Vector2.Dot(segmentToCircle, line) / lineLength;
// Special cases where the closest point happens to be the end points
Vector2 closest;
if (closestPointOnSegment < 0) closest = Start;
else if (closestPointOnSegment > lineLength) closest = End;
else closest = Start + closestPointOnSegment * lineNorm;
// Find that distance. If it is less than the radius, then we
// are within the circle
var distanceFromClosest = pos - closest;
var distanceFromClosestLength = distanceFromClosest.Length();
if (distanceFromClosestLength > radius)
return false;
// So find the distance that places the intersection point right at
// the radius. This is the center of the circle at the time of collision
// and is different than the result from Doswa
var offset = (radius - distanceFromClosestLength) * ((1 / distanceFromClosestLength) * distanceFromClosest);
circleWhenHit = pos - offset;
return true;
}
And this code when the ball wants to change position:
private void GameBall_OnPositionChange(object sender, GameBallPositionChangedEventArgs e)
{
foreach(var boundary in mapBounds)
{
if (boundary.IntersectCircle(e.TargetPosition, gameBall.Radius, out Vector2 colVector))
{
var normalizedVelocity = Vector2.Normalize(e.Velocity);
var velo = e.Velocity.Length();
var surfaceNormal = Vector2.Normalize(colVector - e.CurrentPosition);
e.Velocity = Vector2.Reflect(normalizedVelocity, surfaceNormal) * velo;
e.TargetPosition = e.CurrentPosition;
break;
}
}
}
This code gives a decent result but I'm not using my boundary positions to calculate an angle.
How do I proceed to take those into account?
EDIT:
I've removed the event based update. I've added collision between players and the ball. This is now my map-update method:
foreach (var entity in circleGameEntities)
{
for (int i = 0; i < interpolatePos; i++)
{
entity.UpdatePosition(gameTime, interpolatePos);
var intersectingBoundaries = mapBounds
.Where(b =>
{
var intersects = b.IntersectCircle(entity.Position, entity.Radius, 0f, out _);
if (intersects)
averageNormal += b.Normal;
return intersects;
}).ToList();
if (intersectingBoundaries.Count > 0)
{
averageNormal.Normalize();
var normalizedVelocity = Vector2.Normalize(entity.Velocity); // Normalisera hastigheten
var velo = entity.Velocity.Length();
entity.Velocity = Vector2.Reflect(normalizedVelocity, averageNormal) * velo * entity.Bounciness;
entity.UpdatePosition(gameTime, interpolatePos);
}
foreach (var otherEntity in circleGameEntities.Where(e => e != entity))
{
if (entity.CollidesWithCircle(otherEntity, out Vector2 d))
{
Vector2 CMVelocity = (otherEntity.Mass * otherEntity.Velocity + entity.Mass * entity.Velocity) / (otherEntity.Mass + entity.Mass);
var otherEntityNorm = otherEntity.Position - entity.Position;
otherEntityNorm.Normalize();
var entityNorm = -otherEntityNorm;
var myVelocity = entity.Velocity;
myVelocity -= CMVelocity;
myVelocity = Vector2.Reflect(myVelocity, otherEntityNorm);
myVelocity += CMVelocity;
entity.Velocity = myVelocity;
entity.UpdatePosition(gameTime, interpolatePos);
var otherEntityVelocity = otherEntity.Velocity;
otherEntityVelocity -= CMVelocity;
otherEntityVelocity = Vector2.Reflect(otherEntityVelocity, entityNorm);
otherEntityVelocity += CMVelocity;
otherEntity.Velocity = otherEntityVelocity;
otherEntity.UpdatePosition(gameTime, interpolatePos);
}
}
}
entity.UpdateDrag(gameTime);
entity.Update(gameTime);
}
This code works quite well but sometimes the objects get stuck inside the walls and eachother.
CircleGameEntity class:
class CircleGameEntity : GameEntity
{
internal float Drag { get; set; } = .9999f;
internal float Radius => Scale * (Texture.Width + Texture.Height) / 4;
internal float Bounciness { get; set; } = 1f;
internal float Mass => BaseMass * Scale;
internal float BaseMass { get; set; }
internal Vector2 Velocity { get; set; }
internal float MaxVelocity { get; set; } = 10;
internal void UpdatePosition(GameTime gameTime, int interpolate)
{
var velocity = Velocity;
if (velocity.X < 0 && velocity.X < -MaxVelocity)
velocity.X = -MaxVelocity;
else if (velocity.X > 0 && velocity.X > MaxVelocity)
velocity.X = MaxVelocity;
if (velocity.Y < 0 && velocity.Y < -MaxVelocity)
velocity.Y = -MaxVelocity;
else if (velocity.Y > 0 && velocity.Y > MaxVelocity)
velocity.Y = MaxVelocity;
Velocity = velocity;
Position += Velocity / interpolate;
}
internal void UpdateDrag(GameTime gameTime)
{
Velocity *= Drag;
}
internal bool CollidesWithCircle(CircleGameEntity otherCircle, out Vector2 depth)
{
var a = Position;
var b = otherCircle.Position;
depth = Vector2.Zero;
float distance = Vector2.Distance(a, b);
if (Radius + otherCircle.Radius > distance)
{
float result = (Radius + otherCircle.Radius) - distance;
depth.X = (float)Math.Cos(result);
depth.Y = (float)Math.Sin(result);
}
return depth != Vector2.Zero;
}
}
The surfaceNormal is not the boundary normal, but the angle between the collision point and the center of the circle. This vector takes the roundness of the ball into account and is the negative of the ball's direction(if normalized) as if it hit the surface head-on, which is not needed unless the other surface is curved.
In the Boundary class calculate the angle and one of the normals in the constructor and store them as public readonly:
public readonly Vector2 Angle; // replaces lineNorm for disabiguity
public readonly Vector2 Normal;
public readonly Vector2 Length;
public Boundary(... , bool inside) // inside determines which normal faces the center
{
// ... existing constructor code
var line = End - Start;
Length = line.Length();
Angle = (1 / Length) * line;
Normal = new Vector2(-Angle.Y,Angle.X);
if (inside) Normal *= -1;
}
public bool IntersectCircle(Vector2 pos, float radius)
{
// find the closest point on the line segment to the center of the circle
var segmentToCircle = pos - Start;
var closestPointOnSegment = Vector2.Dot(segmentToCircle, End - Start) / Length;
// Special cases where the closest point happens to be the end points
Vector2 closest;
if (closestPointOnSegment < 0) closest = Start;
else if (closestPointOnSegment > Length) closest = End;
else closest = Start + closestPointOnSegment * Angle;
// Find that distance. If it is less than the radius, then we
// are within the circle
var distanceFromClosest = pos - closest;
return (distanceFromClosest.LengthSquared() > radius * radius); //the multiply is faster than square root
}
The change position code subset:
// ...
var normalizedVelocity = Vector2.Normalize(e.Velocity);
var velo = e.Velocity.Length();
e.Velocity = Vector2.Reflect(normalizedVelocity, boundary.Normal) * velo;
//Depending on timing and movement code, you may need add the next line to resolve the collision during the current step.
e.CurrentPosition += e.Velocity;
//...
This updated code assumes a single-sided non-moving boundary line as prescribed by the inside variable.
I am not a big fan of C# events in games, since it adds layers of delay (both, internally to C# and during proper use the cast of sender.)
I would be remiss not to mention your abuse of the e variable. e should always be treated as a value type: i.e. read-only. The sender variable should be cast(slow) and used for writing purposes.
I made a code that tell me how many positions can the player see on a 2D map.
When I test the code by moving all around the map and testing differents position, it's working. The next step was to create a heatmap of the numbers of position the player can see for every positions. But when I try to run the code, it return false positions.
I've tried different local and global transform methods, and it didn't work
void HtPnt (Vector2 g)
{
int pnt = 0;
foreach (Vector2 f in Q)
{
bool compt = false;
for (int i = 0; i < criticalPointDebug.Length - 1; i++)
{
if (IsInsideTriangle(f, g, criticalPointDebug[i].location, criticalPointDebug[i + 1].location))
compt = true;
}
if (compt == true)
pnt += 1;
}
}
// criticalPointDebug is the list of the visibility polygon, and here's my test in update() :
if (Input.GetKeyDown(KeyCode.A))
{
for (int x=0;x<5;x++)
{
Debug.Log(position);
transform.position = new Vector2(5 + .5f * x, 4);
HtPnt(position);
Debug.Log(position);
}
}
if (Input.GetKeyDown(KeyCode.Z))
{
Debug.Log(position);
transform.position = new Vector2(5,4);
position = new Vector2(5, 4);
HtPnt(position);
Debug.Log(position);
}
first test is returning the correct value of the position on the player (before runing the test) 5 times and the second return nonsense result. Thanks in advance for enlighting me on my problem !
Unity has a function Terrain.sampleHeight(point) which is great, it instantly gives you the height of the Terrain underfoot rather than having to cast.
However, any non-trivial project has more than one Terrain. (Indeed any physically large scene inevitably features terrain stitching, one way or another.)
Unity has a function Terrain.activeTerrain which - I'm not making this up - gives you: the "first one loaded"
Obviously that is completely useless.
Is fact, is there a fast way to get the Terrain "under you"? You can then use the fast function .sampleHeight ?
{Please note, of course, you could ... cast to find a Terrain under you! But you would then have your altitude so there's no need to worry about .sampleHeight !}
In short is there a matching function to use with sampleHeight which lets that function know which Terrain to use for a given xyz?
(Or indeed, is sampleHeight just a fairly useless demo function, usable only in demos with one Terrain?)
Is there in fact a fast way to get the Terrain "under you" - so as to
then use the fast function .sampleHeight ?
Yes, it can be done.
(Or indeed, is sampleHeight just a fairly useless demo function,
usable only in demos with one Terrain?)
No
There is Terrain.activeTerrain which returns the main terrain in the scene. There is also Terrain.activeTerrains (notice the "s" at the end) which returns active terrains in the scene.
Obtain the terrains with Terrain.activeTerrains which returns Terrain array then use Terrain.GetPosition function to obtain its position. Get the current terrain by finding the closest terrain from the player's position. You can do this by sorting the terrain position, using Vector3.Distance or Vector3.sqrMagnitude (faster).
Terrain GetClosestCurrentTerrain(Vector3 playerPos)
{
//Get all terrain
Terrain[] terrains = Terrain.activeTerrains;
//Make sure that terrains length is ok
if (terrains.Length == 0)
return null;
//If just one, return that one terrain
if (terrains.Length == 1)
return terrains[0];
//Get the closest one to the player
float lowDist = (terrains[0].GetPosition() - playerPos).sqrMagnitude;
var terrainIndex = 0;
for (int i = 1; i < terrains.Length; i++)
{
Terrain terrain = terrains[i];
Vector3 terrainPos = terrain.GetPosition();
//Find the distance and check if it is lower than the last one then store it
var dist = (terrainPos - playerPos).sqrMagnitude;
if (dist < lowDist)
{
lowDist = dist;
terrainIndex = i;
}
}
return terrains[terrainIndex];
}
USAGE:
Assuming that the player's position is transform.position:
//Get the current terrain
Terrain terrain = GetClosestCurrentTerrain(transform.position);
Vector3 point = new Vector3(0, 0, 0);
//Can now use SampleHeight
float yHeight = terrain.SampleHeight(point);
While it's possible to do it with Terrain.SampleHeight, this can be simplified with a simple raycast from the player's position down to the Terrain.
Vector3 SampleHeightWithRaycast(Vector3 playerPos)
{
float groundDistOffset = 2f;
RaycastHit hit;
//Raycast down to terrain
if (Physics.Raycast(playerPos, -Vector3.up, out hit))
{
//Get y position
playerPos.y = (hit.point + Vector3.up * groundDistOffset).y;
}
return playerPos;
}
Terrain.GetPosition() = Terrain.transform.position = position in world
working method:
Terrain[] _terrains = Terrain.activeTerrains;
int GetClosestCurrentTerrain(Vector3 playerPos)
{
//Get the closest one to the player
var center = new Vector3(_terrains[0].transform.position.x + _terrains[0].terrainData.size.x / 2, playerPos.y, _terrains[0].transform.position.z + _terrains[0].terrainData.size.z / 2);
float lowDist = (center - playerPos).sqrMagnitude;
var terrainIndex = 0;
for (int i = 0; i < _terrains.Length; i++)
{
center = new Vector3(_terrains[i].transform.position.x + _terrains[i].terrainData.size.x / 2, playerPos.y, _terrains[i].transform.position.z + _terrains[i].terrainData.size.z / 2);
//Find the distance and check if it is lower than the last one then store it
var dist = (center - playerPos).sqrMagnitude;
if (dist < lowDist)
{
lowDist = dist;
terrainIndex = i;
}
}
return terrainIndex;
}
It turns out the answer is simply NO, Unity does not provide such a function.
You can use this function to get the Closest Terrain to your current Position:
int GetClosestTerrain(Vector3 CheckPos)
{
int terrainIndex = 0;
float lowDist = float.MaxValue;
for (int i = 0; i < _terrains.Length; i++)
{
var center = new Vector3(_terrains[i].transform.position.x + _terrains[i].terrainData.size.x / 2, CheckPos.y, _terrains[i].transform.position.z + _terrains[i].terrainData.size.z / 2);
float dist = Vector3.Distance(center, CheckPos);
if (dist < lowDist)
{
lowDist = dist;
terrainIndex = i;
}
}
return terrainIndex;
}
and then you can use the function like this:
private Terrain[] _terrains;
void Start()
{
_terrains = Terrain.activeTerrains;
Vector3 start_pos = Vector3.zero;
start_pos.y = _terrains[GetClosestTerrain(start_pos)].SampleHeight(start_pos);
}
public static Terrain GetClosestTerrain(Vector3 position)
{
return Terrain.activeTerrains.OrderBy(x =>
{
var terrainPosition = x.transform.position;
var terrainSize = x.terrainData.size * 0.5f;
var terrainCenter = new Vector3(terrainPosition.x + terrainSize.x, position.y, terrainPosition.z + terrainSize.z);
return Vector3.Distance(terrainCenter, position);
}).First();
}
Raycast solution: (this was not asked, but for those looking for Solution using Raycast)
Raycast down from Player, ignore everything that has not Layer of "Terrain" (Layer can be easily set in inspector).
Code:
void Update() {
// Put this on Player! Raycast's down (raylength=10f), if we hit something, check if the Layers name is "Terrain", if yes, return its instanceID
RaycastHit hit;
if (Physics.Raycast (transform.localPosition, transform.TransformDirection (Vector3.down), out hit, 10f, 1 << LayerMask.NameToLayer("Terrain"))) {
Debug.Log(hit.transform.gameObject.GetInstanceID());
}
}
At this point already, you have a reference to the Terrain by "hit.transform.gameObject".
For my case, i wanted to reference this terrain by its instanceID:
// any other script
public static UnityEngine.Object FindObjectFromInstanceID(int goID) {
return (UnityEngine.Object)typeof(UnityEngine.Object)
.GetMethod("FindObjectFromInstanceID", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
.Invoke(null, new object[] { goID });
}
But as written above, if you want the Terrain itself (as Terrain object) and not the instanceID, then "hit.transform.gameObject" will give you the reference already.
Input and code snippets taken from these links:
https://answers.unity.com/questions/1164722/raycast-ignore-layers-except.html
https://answers.unity.com/questions/34929/how-to-find-object-using-instance-id-taken-from-ge.html
Ok, I am having a problem with a Unity scroll panel in C#. I downloaded this character picker that consists of a script attached to a scroll panel from here:
https://www.youtube.com/watch?v=YBsGhYuTavA
It works very well but problem is I cant make it scroll vertically instead of horizontal. I have checked the "vertical" boolean instead of horizontal on the actual scroll panel then in the script I have changed the places that based off x values to y values.
I commented where, here is the script:
float[] distance;
bool dragging = false;
int minButtonNum;
int currentSelectedPly = -1;
public float objectScale = 1.7f;
public int bttnDistance = 300;
void OnEnable() {
//txtGeneralCash.text = "" + PlayerPrefs.GetInt ("money", 0);
}
void Start(){
distance = new float[prefab.Length];
//instatiate the prefab
for(int i=0; i<prefab.Length;i++){
prefab[i] = Instantiate(prefab[i],center.transform.position,camInUse.transform.rotation) as GameObject;
prefab [i].transform.SetParent(panel.transform);
Vector3 pos = prefab[i].GetComponent<RectTransform>().anchoredPosition;
pos.x += (i * bttnDistance); //**CHANGED TO POS.Y
prefab [i].GetComponent<RectTransform> ().anchoredPosition = pos;
}
}
void Update(){
//calculate the relative distance
for(int i=0;i<prefab.Length;i++){
distance [i] = Mathf.Abs (center.transform.position.x - prefab [i].transform.position.x); //CHANGED THESE TO .Y
}
float minDistance = Mathf.Min (distance);
// Aplly the scale to object
for(int a=0;a<prefab.Length;a++){
if (minDistance == distance [a]) {
minButtonNum = a;
//this is when each char is selected !!!!!!!!!!!!!!!
if(minButtonNum != currentSelectedPly){
//lookAtPrice (minButtonNum);
scaleButtonCenter (minButtonNum);
currentSelectedPly = minButtonNum;
txtName.text = prefab [minButtonNum].GetComponent<CharacterProperty> ().nameObj;
bgMat.color = prefab [minButtonNum].GetComponent<CharacterProperty> ().color;
}
}
}
// if the users aren't dragging the lerp function is called on the prefab
if(!dragging){
LerpToBttn (currentSelectedPly* (-bttnDistance));
}
}
/*
* Lerp the nearest prefab to center
*/
void LerpToBttn(int position){
float newX = Mathf.Lerp (panel.anchoredPosition.x,position,Time.deltaTime*7f); //CHANGED TO .Y
Vector2 newPosition = new Vector2 (newX,panel.anchoredPosition.y);
panel.anchoredPosition = newPosition;
}
/*
* Set the scale of the prefab on center to 2, other to 1
*/
public void scaleButtonCenter (int minButtonNum){
for (int a = 0; a < prefab.Length; a++) {
if (a == minButtonNum) {
StartCoroutine (ScaleTransform(prefab [a].transform,prefab [a].transform.localScale,new Vector3 (objectScale,objectScale,objectScale)));
} else {
StartCoroutine (ScaleTransform(prefab [a].transform,prefab [a].transform.localScale,new Vector3 (1f, 1f, 1f)));
}
}
}
/*
* If the prefab is not free, show the price button
/*
* Courutine for change the scale
*/
IEnumerator ScaleTransform(Transform transformTrg,Vector3 initScale,Vector3 endScale){
float completeTime = 0.2f;//How much time will it take to scale
float currentTime = 0.0f;
bool done = false;
while (!done){
float percent = currentTime / completeTime;
if (percent >= 1.0f){
percent = 1;
done = true;
}
transformTrg.localScale = Vector3.Lerp(initScale, endScale, percent);
currentTime += Time.deltaTime;
yield return new WaitForEndOfFrame();
}
}
/*
* Called by the canvas, set dragging to true for preventing lerp when users are dragging
*/
public void StartDrag(){
dragging = true;
}
/*
* Called by the canvas, set dragging to true for preventing lerp when users are dragging
*/
public void EndDrag(){
dragging = false;
}
/*
* Called when character is selected, it change the player model
*/
public void CharacterSelected(){
bool oneEnable = false;
string nameSelected = prefab [currentSelectedPly].GetComponent<CharacterProperty> ().name;
nameSelected = nameSelected.Split('(')[0];
GameObject player = GameObject.Find ("CharactersPlayer");
if(player != null){
foreach (Transform child in player.transform) {
if (child.gameObject.name == nameSelected) {
child.gameObject.SetActive (true);
oneEnable = true;
PlayerPrefs.SetString ("SelectedPlayer", nameSelected);
} else {
child.gameObject.SetActive (false);
}
}
// if no one was selected
if (oneEnable == false) {
player.transform.GetChild (0).gameObject.SetActive (true);
}
}
}
Ive gone through it several times and I don't know why just changing the values from .x to .y does not work. I get a bunch of glitching and the characters do stack up vertically, but they move off the screen when i try to scroll.
How can I fix this?
I created a series of sphere clones in my game. After that I adapted the scale so that they appear smaller. However, now there is a gap between these spheres ... and I would have to change the position of this instatiate game objects. I changed my code already exactly at this position but nothing happens. So please I need your help! How can I do this? I would have very small spheres which are located near together.
Here the code:
using UnityEngine;
using System.Collections;
public class SineWave : MonoBehaviour {
private GameObject plotPointObject;
private int numberOfPoints= 100;
private float animSpeed =1.0f;
private float scaleInputRange = 8*Mathf.PI; // scale number from [0 to 99] to [0 to 2Pi] //Zahl vor Mathf, Anzahl Bön
private float scaleResult = 2.5f; // Y Achse Range
public bool animate = true;
GameObject[] plotPoints;
// Use this for initialization
void Start () {
if (plotPointObject == null) //if user did not fill in a game object to use for the plot points
plotPointObject = GameObject.CreatePrimitive(PrimitiveType.Sphere); //create a sphere
//add Material to the spheres , load material in the folder Resources/Materials
Material myMaterial = Resources.Load("Materials/green", typeof(Material)) as Material;
plotPointObject.GetComponent<MeshRenderer> ().material = myMaterial;
//change the scale of the spheres
//plotPointObject.transform.localScale = Vector3.one * 0.5f ;
plotPointObject.transform.localScale -= new Vector3(0.5f,0.5f,0.5f);
plotPoints = new GameObject[numberOfPoints]; //creat an array of 100 points.
//plotPointObject.GetComponent<MeshRenderer> ().material =Material.Load("blue") as Material
//plotPointObject.transform.localScale -= new Vector3 (0.5F, 0.5F, 0.5F); //neu: change the scale of the spheres
for (int i = 0; i < numberOfPoints; i++)
{
plotPoints[i] = (GameObject)GameObject.Instantiate(plotPointObject, new Vector3(i -
(numberOfPoints/2), 0, 0), Quaternion.identity); //this specifies
what object to create, where to place it and how to orient it
}
//we now have an array of 100 points- your should see them in the hierarchy when you hit play
plotPointObject.SetActive(false); //hide the original
}
Thank you already in advance!
Edit:
As I said in the comment I achieved now to place my spheres without a gap in between. However, as soon as I animate my spheres (with a sine wave) there is still that gap between the spheres. How can I adapt this? Should I copy the code of the Start function in the Update function?
I would be very happy to get some help. Thank you very much!
enter code here void Update()
{
for (int i = 0; i < numberOfPoints; i++)
{
float functionXvalue = i * scaleInputRange / numberOfPoints; // scale number from [0 to 99] to [0 to 2Pi]
if (animate)
{
functionXvalue += Time.time * animSpeed;
}
plotPoints[i].transform.position = new Vector3(i - (numberOfPoints/2), ComputeFunction(functionXvalue) * scaleResult, 0);
//print (plotPointObject.GetComponent<MeshRenderer> ().bounds.size.x);
// put the position information of sphere clone 50 in a vector3 named posSphere
posSphere = plotPoints [50].transform.position;
}
//print position of sphere 50 in console
//print (posSphere);
}
float ComputeFunction(float x)
{
return Mathf.Sin(x);
}
}
I think you could make the Barış solution.
For each new object that you are instantiating, you will set his position to the lasted instantiated position adding the size of the object itself, or whatever distance that you want they have from each other.
var initialPosition = 0;
var distanceFromEachOther = 20;
for (int i = 0; i < numberOfPoints; i++) {
var newPos = new Vector3(initialPosition + (i * distanceFromEachOther), 0, 0);
plotPoints[i] = (GameObject)GameObject.Instantiate(plotPointObject, newPos, Quaternion.identity);
}
That will make a gap between the spheres at X pivot, depending on their size. Change the distanceFromEachOther var, adjusting for your needs.
You could also get the object distance with plotPointObject.GetComponent<MeshRenderer>().bounds.size, so distanceFromEachOther could be, for example distanceFromEachOther = plotPointObject.GetComponent<MeshRenderer>().bounds.size.x + 5. So then you will have the objects with a perfectly distance of 5 from each other.
give this a try:
Transform objectToSpawn;
for (int i = 0; i < numberOfPoints; i++)
{
float someX = 200;
float someY = 200;
Transform t = Instantiate(objectToSpawn, new Vector3(i -(numberOfPoints/2), 0, 0), Quaternion.identity) as Transform;
plotPoints[i] = t.gameObject;
t.position = new Vector(someX, someY);
}