how to show next image in a carousel view in c#? - c#

I am creating a carousel view with next and previous buttons to show the previous and next images. When I am clicking the Next button it doesn't get to next image, it stays the same. Can anyone help me solve this issue.
Here is what I've tried so far:
// Declare variables.
public RectTransform window;
public bool startWelcomeScreen;
public RectTransform[] introImages;
private float wide;
private float mousePositionStartX;
private float mousePositionEndX;
private float dragAmount;
private float screenPosition;
private float lastScreenPosition;
private float lerpTimer;
private float lerpPage;
public int pageCount = 1;
public string side = "";
public int swipeThrustHold = 30;
public int spaceBetweenProfileImages = 30;
private bool canSwipe;
public GameObject cartoonWindow;
public Texture2D userPic;
void Start() {
wide = cartoonWindow.GetComponent<RectTransform>().rect.width;
for(int i = 1; i < introImages.Length; i++){
introImages[i].anchoredPosition = new Vector2(((wide+spaceBetweenProfileImages)*i),0);
}
side = "right";
startWelcomeScreen = true;
}
public void NextButtonIsTapped()
{
cartoonWindow.SetActive(true);
}
void Update() {
if(!startWelcomeScreen)
return;
lerpTimer=lerpTimer+Time.deltaTime;
if(lerpTimer<.333){
screenPosition = Mathf.Lerp(lastScreenPosition ,lerpPage*-1 , lerpTimer*3);
lastScreenPosition=screenPosition;
}
if(Input.GetMouseButtonDown(0) && Input.mousePosition.y > (Screen.height*0.6173f) && Input.mousePosition.y < (Screen.height*0.91f) ) {
canSwipe = true;
mousePositionStartX = Input.mousePosition.x;
}
if(Input.GetMouseButton(0)) {
if(canSwipe){
mousePositionEndX = Input.mousePosition.x;
dragAmount=mousePositionEndX-mousePositionStartX;
screenPosition=lastScreenPosition+dragAmount;
}
}
if(Mathf.Abs(dragAmount) > swipeThrustHold && canSwipe){
canSwipe = false;
lastScreenPosition=screenPosition;
if(pageCount < introImages.Length )
OnSwipeComplete () ;
else if(pageCount == introImages.Length && dragAmount < 0)
lerpTimer=0;
else if(pageCount == introImages.Length && dragAmount > 0)
OnSwipeComplete () ;
}
if(Input.GetMouseButtonUp(0)) {
if(Mathf.Abs(dragAmount) < swipeThrustHold) {
lerpTimer = 0;
}
}
for(int i = 0; i < introImages.Length; i++){
introImages[i].anchoredPosition = new Vector2(screenPosition+((wide+spaceBetweenProfileImages)*i),0);
if(side == "right") {
if(i == pageCount-1) {
introImages[i].localScale = Vector3.Lerp(introImages[i].localScale,new Vector3(1.2f,1.2f,1.2f),Time.deltaTime*5);
Color temp = introImages[i].GetComponent<Image>().color;
introImages[i].GetComponent<Image>().color = new Color(temp.r,temp.g,temp.b,1);
} else {
introImages[i].localScale = Vector3.Lerp(introImages[i].localScale,new Vector3(0.7f,0.7f,0.7f),Time.deltaTime*5);
Color temp = introImages[i].GetComponent<Image>().color;
introImages[i].GetComponent<Image>().color = new Color(temp.r,temp.g,temp.b,0.5f);
}
} else {
if(i == pageCount) {
introImages[i].localScale = Vector3.Lerp(introImages[i].localScale,new Vector3(1.2f,1.2f,1.2f),Time.deltaTime*5);
Color temp = introImages[i].GetComponent<Image>().color;
introImages[i].GetComponent<Image>().color = new Color(temp.r,temp.g,temp.b,1);
} else {
introImages[i].localScale = Vector3.Lerp(introImages[i].localScale,new Vector3(0.7f,0.7f,0.7f),Time.deltaTime*5);
Color temp = introImages[i].GetComponent<Image>().color;
introImages[i].GetComponent<Image>().color = new Color(temp.r,temp.g,temp.b,0.5f);
}
}
}
}
#endregion
I don't get any errors though but it's just don't get to next image.

Looking at the code above I would suggest you create a parent gameobject around the introImages and rather move it's anchored position and not move each image. By moving the anchored position of the parent, all the child images will move within the mask.
To include paging buttons to move next and previous, you could do:
void Start () {
rectTransform = sliderWrapper.GetComponent<RectTransform> (); // parent wrapper
currentItem = 0; // start x position of the wrapper
itemWidth = 1000f; // width of the images
itemCount = sliderWrapper.transform.childCount; // number of images
}
Then in your next and previous methods, you move the parent's anchoredPosition:
public void Next () {
currentItem++; // the next image
rectTransform.anchoredPosition = new Vector2 (-currentItem * itemWidth, 0); // move the x position by the currentItem (the index) multiplied by image width
prevButton.interactable = true;
if (currentItem == itemCount - 1) {
nextButton.interactable = false;
}
}
public void Prev () {
currentItem--; // previous image
rectTransform.anchoredPosition = new Vector2 (-currentItem * itemWidth, 0); // move the x position by the currentItem (the index) multiplied by image width
if (currentItem == 0) {
prevButton.interactable = false;
}
if (currentItem < itemCount) {
nextButton.interactable = true;
}
}
UPDATE
Some steps to help outline the above. Note no animation is in place, it simply jumps to the relevant slider item.
1) Add a GameObject, called Slider below, with a Rect Mask 2D component and set the rect transform width/height to match a single image's width/height. This will mask out the overflowing children.
2) Add a GameObject, called Item Wrapper below, with a Horizontal Layout Group component and a Content Size Fitter and set properties like below to allow it to scale the game object's rect transform width according to the children and also layout the images horizontally:
Now all you need to do is update the Slider Wrapper's anchoredPosition. This will move the wrapper within the parent Slider GameObject. As the Slider GameObject has a mask on it, we don't see any of the overflowing items.
[SerializeField]
Button nextButton;
[SerializeField]
Button prevButton;
[SerializeField]
GameObject sliderWrapper;
float itemWidth;
int itemCount;
int currentItem;
RectTransform rectTransform;
void Start () {
rectTransform = sliderWrapper.GetComponent<RectTransform> ();
currentItem = 0;
itemWidth = 1000f; // width of your slider/image
itemCount = sliderWrapper.transform.childCount;
}
public void Next () {
currentItem++;
rectTransform.anchoredPosition = new Vector2 (-currentItem * itemWidth, 0);
prevButton.interactable = true;
if (currentItem == itemCount - 1) {
nextButton.interactable = false;
}
}
public void Prev () {
currentItem--;
rectTransform.anchoredPosition = new Vector2 (-currentItem * itemWidth, 0);
if (currentItem == 0) {
prevButton.interactable = false;
}
if (currentItem < itemCount) {
nextButton.interactable = true;
}
}
BONUS
Code to animate the slider:
public void Next () {
currentItem++;
prevButton.interactable = false;
nextButton.interactable = false;
StartCoroutine (SlideTo (new Vector2 (-currentItem * itemWidth, 0), () => {
prevButton.interactable = true;
if (currentItem < itemCount - 1) {
nextButton.interactable = true;
}
}));
}
public void Prev () {
currentItem--;
prevButton.interactable = false;
nextButton.interactable = false;
StartCoroutine (SlideTo (new Vector2 (-currentItem * itemWidth, 0), () => {
if (currentItem > 0) {
prevButton.interactable = true;
}
if (currentItem < itemCount) {
nextButton.interactable = true;
}
}));
}
IEnumerator SlideTo (Vector2 position, Action callback = null, float timeToMove = .5f) {
var t = 0f;
while (t < 1) {
t += Time.deltaTime / timeToMove;
rectTransform.anchoredPosition = Vector2.Lerp (rectTransform.anchoredPosition, position, t);
yield return new WaitForEndOfFrame ();
}
if (callback != null) {
callback ();
}
}

Related

how to make line renderer stay flat on the surface?

I am drawing a line renderer between two navmesh agents and assigning a direction arrow texture to it. But the problem is that it is standing vertically on top of my road structure. I need to make a lie down flat.
The code for drawing lines between two agents:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class ParkingLevel : MonoBehaviour
{
[Space(10)]
[Header("For Path Rendering")]
public Transform targetAgent;
public NavMeshAgent agent_ParkingPoint;
public LineRenderer line;
public static ParkingLevel Instance;
void OnEnable()
{
if (Instance == null)
{
Instance = this;
line.startWidth = 3;
line.endWidth = 3;
return;
}
}
void OnDisable()
{
Instance = null;
}
void LateUpdate()
{
GetPath();
}
public void GetPath()
{
targetAgent = PlayerActivitiesManager.Instance.busAgent.transform;
line.SetPosition(0, agent_ParkingPoint.gameObject.transform.position);
agent_ParkingPoint.SetDestination(targetAgent.position);
DrawPath(agent_ParkingPoint.path);
agent_ParkingPoint.isStopped = true;
}
private void DrawPath(NavMeshPath path)
{
if (path.corners.Length < 2)
return;
line.positionCount = path.corners.Length;
for (var i = 1; i < path.corners.Length; i++)
{
line.SetPosition(i, path.corners[i]);
}
}
}
Here are my settings for the line renderer:
You could use a little trick:
Set the LineRenderer to position = Vector3.zero
Set Use World Space = false -> will use local space positions
Rotate the line to x = 90°
Finally now you have to alter the positions slightly and flip Z and Y axis
so something like e.g.
void OnEnable()
{
if (Instance == null)
{
Instance = this;
line.startWidth = 3;
line.endWidth = 3;
line.useWorldSpace = false;
var lineTransform = line.transform;
lineTransform.parent = null;
lineTransform.position = Vector3.zero;
lineTransform.localScale = Vector3.one;
line.transform.rotation = Quaternion.Euler(90, 0, 0);
}
}
private void DrawPath(NavMeshPath path)
{
if (path.corners.Length < 2)
{
line.enabled = false;
return;
}
line.enabled = true;
var flippedPositions = new Vector3[path.corners.Length];
var firstPosition = agent_ParkingPoint.transform.position;
var fistFlippedPosition = new Vector3(firstPosition.x, firstPosition.z, firstPosition.y);
flippedPositions[0] = fistFlippedPosition;
for (var i = 1; i < path.corners.Length; i++)
{
var p = path.corners[i];
flippedPositions[i] = new Vector3(p.x, p.z, p.y);
}
line.positionCount = flippedPositions.Length;
line.SetPositions(flippedPositions);
}

How to make a continuous rotation by changing this c# code

Im using Unity and have asked this on there forums however have not had any replies. Ive found this example from a plugin where I am trying to use the kinect to rotate an object using my right hand to rotate it right and the left to rotate left. I have managed to get the object to do this apart from it stops at each side of the object, but cant work out what part of the code is doing this.
Thanks
using UnityEngine;
using System.Collections;
using System;
public class GestureListener : MonoBehaviour, KinectGestures.GestureListenerInterface
{
// GUI Text to display the gesture messages.
public GUIText GestureInfo;
private bool raiselefthand;
private bool raiserighthand;
public bool IsSwipeLeft()
{
if(raiserighthand)
{
raiserighthand = false;
return true;
}
return false;
}
public bool IsSwipeRight()
{
if(raiselefthand)
{
raiselefthand = false;
return true;
}
return false;
}
public void UserDetected(uint userId, int userIndex)
{
// detect these user specific gestures
KinectManager manager = KinectManager.Instance;
manager.DetectGesture(userId, KinectGestures.Gestures.RaiseLeftHand);
manager.DetectGesture(userId, KinectGestures.Gestures.RaiseRightHand);
if(GestureInfo != null)
{
GestureInfo.GetComponent<GUIText>().text = "Swipe left or right to change the slides.";
}
}
public void UserLost(uint userId, int userIndex)
{
if(GestureInfo != null)
{
GestureInfo.GetComponent<GUIText>().text = string.Empty;
}
}
public void GestureInProgress(uint userId, int userIndex, KinectGestures.Gestures gesture,
float progress, KinectWrapper.NuiSkeletonPositionIndex joint, Vector3 screenPos)
{
// don't do anything here
}
public bool GestureCompleted (uint userId, int userIndex, KinectGestures.Gestures gesture,
KinectWrapper.NuiSkeletonPositionIndex joint, Vector3 screenPos)
{
string sGestureText = gesture + " detected";
if(GestureInfo != null)
{
GestureInfo.GetComponent<GUIText>().text = sGestureText;
}
if(gesture == KinectGestures.Gestures.RaiseRightHand)
raiserighthand = true;
else if(gesture == KinectGestures.Gestures.RaiseLeftHand)
raiselefthand = true;
return true;
}
public bool GestureCancelled (uint userId, int userIndex, KinectGestures.Gestures gesture,
KinectWrapper.NuiSkeletonPositionIndex joint)
{
// don't do anything here, just reset the gesture state
return true;
}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PresentationScript : MonoBehaviour
{
public bool slideChangeWithGestures = true;
public bool slideChangeWithKeys = true;
public float spinSpeed = 5;
public bool autoChangeAlfterDelay = false;
public float slideChangeAfterDelay = 10;
public List<Texture> slideTextures;
public List<GameObject> horizontalSides;
// if the presentation cube is behind the user (true) or in front of the user (false)
public bool isBehindUser = false;
private int maxSides = 0;
private int maxTextures = 0;
private int side = 0;
private int tex = 0;
private bool isSpinning = false;
private float slideWaitUntil;
private Quaternion targetRotation;
private GestureListener gestureListener;
void Start()
{
// hide mouse cursor
Cursor.visible = false;
// calculate max slides and textures
maxSides = horizontalSides.Count;
maxTextures = slideTextures.Count;
// delay the first slide
slideWaitUntil = Time.realtimeSinceStartup + slideChangeAfterDelay;
targetRotation = transform.rotation;
isSpinning = false;
tex = 0;
side = 0;
if(horizontalSides[side] && horizontalSides[side].GetComponent<Renderer>())
{
horizontalSides[side].GetComponent<Renderer>().material.mainTexture = slideTextures[tex];
}
// get the gestures listener
gestureListener = Camera.main.GetComponent<GestureListener>();
}
void Update()
{
// dont run Update() if there is no user
KinectManager kinectManager = KinectManager.Instance;
if(autoChangeAlfterDelay && (!kinectManager || !kinectManager.IsInitialized() || !kinectManager.IsUserDetected()))
return;
if(!isSpinning)
{
if(slideChangeWithKeys)
{
if(Input.GetKeyDown(KeyCode.PageDown))
RotateToNext();
else if(Input.GetKeyDown(KeyCode.PageUp))
RotateToPrevious();
}
if(slideChangeWithGestures && gestureListener)
{
if(gestureListener.IsSwipeLeft())
RotateToNext();
else if(gestureListener.IsSwipeRight())
RotateToPrevious();
}
// check for automatic slide-change after a given delay time
if(autoChangeAlfterDelay && Time.realtimeSinceStartup >= slideWaitUntil)
{
RotateToNext();
}
}
else
{
// spin the presentation
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, spinSpeed * Time.deltaTime);
// check if transform reaches the target rotation. If yes - stop spinning
float deltaTargetX = Mathf.Abs(targetRotation.eulerAngles.x - transform.rotation.eulerAngles.x);
float deltaTargetY = Mathf.Abs(targetRotation.eulerAngles.y - transform.rotation.eulerAngles.y);
if(deltaTargetX < 1f && deltaTargetY < 1f)
{
// delay the slide
slideWaitUntil = Time.realtimeSinceStartup + slideChangeAfterDelay;
isSpinning = false;
}
}
}
private void RotateToNext()
{
// set the next texture slide
tex = (tex + 1) % maxTextures;
if(!isBehindUser)
{
side = (side + 1) % maxSides;
}
else
{
if(side <= 0)
side = maxSides - 1;
else
side -= 1;
}
if(horizontalSides[side] && horizontalSides[side].GetComponent<Renderer>())
{
horizontalSides[side].GetComponent<Renderer>().material.mainTexture = slideTextures[tex];
}
// rotate the presentation
float yawRotation = !isBehindUser ? 360f / maxSides : -360f / maxSides;
Vector3 rotateDegrees = new Vector3(0f, yawRotation, 0f);
targetRotation *= Quaternion.Euler(rotateDegrees);
isSpinning = true;
}
private void RotateToPrevious()
{
// set the previous texture slide
if(tex <= 0)
tex = maxTextures - 1;
else
tex -= 1;
if(!isBehindUser)
{
if(side <= 0)
side = maxSides - 1;
else
side -= 1;
}
else
{
side = (side + 1) % maxSides;
}
if(horizontalSides[side] && horizontalSides[side].GetComponent<Renderer>())
{
horizontalSides[side].GetComponent<Renderer>().material.mainTexture = slideTextures[tex];
}
// rotate the presentation
float yawRotation = !isBehindUser ? -360f / maxSides : 360f / maxSides;
Vector3 rotateDegrees = new Vector3(0f, yawRotation, 0f);
targetRotation *= Quaternion.Euler(rotateDegrees);
isSpinning = true;
}
}
I have managed to get the object to do this apart from it stops at each side of the object, but cant work out what part of the code is doing this.
I understand you ask for help finding which parts are involved in the rotation.
As such, I looked through the scripts and noticed 2 sections in the PresentationScript.
This part in the Update() method. Based on the code and the comments that are part of it.
// spin the presentation
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, spinSpeed * Time.deltaTime);
// check if transform reaches the target rotation. If yes - stop spinning
float deltaTargetX = Mathf.Abs(targetRotation.eulerAngles.x - transform.rotation.eulerAngles.x);
float deltaTargetY = Mathf.Abs(targetRotation.eulerAngles.y - transform.rotation.eulerAngles.y);
if(deltaTargetX < 1f && deltaTargetY < 1f)
{
// delay the slide
slideWaitUntil = Time.realtimeSinceStartup + slideChangeAfterDelay;
isSpinning = false;
}
This line in the Start() method is also involved.
targetRotation = transform.rotation;
A transform controls the position, scaling and as is relevant for this case, also the rotation of an object.

How to exchange instantiated tilesprefabs from deactivated tiles to activetiles?

Hi everyone I have been making and experimenting on an 3d endless runner game and came with an issue. Here is what I meant to achieve. I have two list of gameobjects called activeTiles and deactivatedTiles. According to my idea I want to first add all the prefab tiles to the deactivatedtTiles list. Next I have a float amtTileOnScreen variable which controls the amount of tiles put in front of the player to run. Then I take a random Tile from the list of deactivated tiles to activated tiles by considering the amount of tiles o screen and put in-front of the player. Used tiles are put back to deactivated tile list and the whole cycle begins.
The question is how do I achieve this? Help would be appreciated.
Here's what I have tried.
public class TileManager : MonoBehaviour
{
public GameObject[] tilePrefabs;
private Transform playerTransform;
private float spawnZ = -12f;
private float tileLength = 24.0f;
private int amtOfTilesOnScreen = 5;
private float safeZone = 56.0f;
private GameObject spawnedTile;
public static List<GameObject> activeTiles;
public static List<GameObject> deactivatedTiles;
private int lastPrefabIndex = 0;
private Vector3 transformTiles;
// Use this for initialization
void Start ()
{
activeTiles = new List<GameObject>();
deactivatedTiles = new List<GameObject>();
playerTransform = GameObject.FindGameObjectWithTag("Player").transform;
for (int i = 0; i < amtOfTilesOnScreen; i++)
{
if (i < 1)
{
activeTiles.Add(SpawnTileAtFront(0));
}
else
{
activeTiles.Add(SpawnTileAtFront());
}
}
}
void Update ()
{
if (playerTransform.position.z - safeZone > (spawnZ - amtOfTilesOnScreen * tileLength))
{
for (int i = 0; i < tilePrefabs.Length; i++)
{
spawnedTile = SpawnTileAtFront();
deactivatedTiles.Add(spawnedTile);
Debug.Log(deactivatedTiles.Count);
}
if (activeTiles.Count < (amtOfTilesOnScreen + 1))
{
activeTiles.Add(GetRandomDeactivatedTile());
MoveTileToTheFront(GetRandomDeactivatedTile());
}
else
{
var disposeTile = activeTiles[0];
deactivatedTiles.Add(disposeTile);
DisposeActiveTiles(0);
}
}
}
private void MoveTileToTheFront(GameObject tile)
{
tile.transform.position = Vector3.forward * spawnZ;
spawnZ += tileLength;
}
private GameObject SpawnTileAtFront(int prefabIndex = -1)
{
GameObject go;
if (prefabIndex == -1)
{
go = Instantiate(tilePrefabs[RandomPrefabIndex()]) as GameObject;
}
else
{
go = Instantiate(tilePrefabs[prefabIndex]) as GameObject;
}
go.transform.SetParent(transform);
MoveTileToTheFront(go);
return go;
}
private void DisposeActiveTiles(int index)
{
GameObject unusedTile = activeTiles[index];
activeTiles.RemoveAt(index);
deactivatedTiles.Add(unusedTile);
}
private GameObject GetRandomDeactivatedTile()
{
if (deactivatedTiles.Count == 0)
return null;
int randomIndex = Random.Range(0, deactivatedTiles.Count);
GameObject unusedTile = deactivatedTiles[randomIndex];
deactivatedTiles.RemoveAt(randomIndex);
return unusedTile;
}
private int RandomPrefabIndex()
{
if (tilePrefabs.Length <= 0)
{
return 0;
}
int randomIndex = lastPrefabIndex;
while (randomIndex == lastPrefabIndex)
{
randomIndex = Random.Range(0, tilePrefabs.Length);
}
lastPrefabIndex = randomIndex;
return lastPrefabIndex;
}
}
void Update ()
{
while (playerTransform.position.z - safeZone > (spawnZ - amtOfTilesOnScreen * tileLength))
{
// we need to add a new tile in front of the player
GameObject t;
if (deactivatedTiles.Count == 0) {
// no deactivated tiles so we need to instantiate a new tile
t = SpawnTileAtFront ();
} else {
// otherwise take deactivated tile into use
t = GetRandomDeactivatedTile ();
MoveTileToTheFront (t);
}
// new tile is now active tile
activeTiles.Add (t);
// take oldest active tile and move it to deactivated list
DisposeActiveTiles(0);
}
}

How can i keep update the targets array when destroying and creating new objects again?

The problem is in this script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class PatrolData
{
public Transform target = null;
public float minDistance = 5f;
public float lingerDuration = 5f;
public float desiredHeight = 10f;
public float flightSmoothTime = 10f;
public float maxFlightspeed = 10f;
public float flightAcceleration = 1f;
public float levelingSmoothTime = 0.5f;
public float maxLevelingSpeed = 10000f;
public float levelingAcceleration = 2f;
}
public class PatrolOverTerrain : MonoBehaviour
{
public FlyToOverTerrain flyOverTerrain;
public LookAtCamera lookAtCamera;
public enum PatrolMode { Clamp, Wrap, PingPong };
public PatrolData[] patrolPoints;
public PatrolMode mode = PatrolMode.Wrap;
private int iterator = 0;
private int index = 0;
private float lingerDuration = 0f;
private int oldLength = 0;
public List<GameObject> TeleportationBooths = new List<GameObject>();
public Vector3 distanceFromTarget;
private void Start()
{
GameObject[] tempObj = GameObject.FindGameObjectsWithTag("Teleportation Booth");
for (int i = 0; i < tempObj.Length; i++)
{
//Add to list only if it does not exist
if (!TeleportationBooths.Contains(tempObj[i]))
{
TeleportationBooths.Add(tempObj[i]);
}
}
//Get the current Size
if (tempObj != null)
{
oldLength = tempObj.Length;
}
GeneratePatrolPoints();
}
private void OnEnable()
{
if (patrolPoints.Length > 0)
{
lingerDuration = patrolPoints[index].lingerDuration;
}
}
private void Update()
{
//Check if oldLength has changed
if (oldLength != TeleportationBooths.Count)
{
//Update oldLength
oldLength = TeleportationBooths.Count;
//Call your the function
GeneratePatrolPoints();
}
int length = patrolPoints.Length;
if (!flyOverTerrain) return;
if (patrolPoints.Length < 1) return;
if (index < 0) return;
// Getting exception out of index on line 89.
// Need to make a list also for the Cubes(buildings).
var patrol = patrolPoints[index];
if (lingerDuration <= 0)
{
iterator++;
switch (mode)
{
case PatrolMode.Clamp:
index = (iterator >= length) ? -1 : iterator;
break;
case PatrolMode.Wrap:
iterator = Modulus(iterator, length);
index = iterator;
break;
case PatrolMode.PingPong:
index = PingPong(iterator, length);
break;
}
if (index < 0) return;
patrol = patrolPoints[index];
flyOverTerrain.target = patrol.target;
flyOverTerrain.desiredHeight = patrol.desiredHeight;
flyOverTerrain.flightSmoothTime = patrol.flightSmoothTime;
flyOverTerrain.maxFlightspeed = patrol.maxFlightspeed;
flyOverTerrain.flightAcceleration = patrol.flightAcceleration;
flyOverTerrain.levelingSmoothTime = patrol.levelingSmoothTime;
flyOverTerrain.maxLevelingSpeed = patrol.maxLevelingSpeed;
flyOverTerrain.levelingAcceleration = patrol.levelingAcceleration;
lookAtCamera.target = patrol.target;
lookAtCamera.RotationSpeed = 3;
lingerDuration = patrolPoints[index].lingerDuration;
}
Vector3 targetOffset = Vector3.zero;
if ((bool)patrol.target)
{
targetOffset = transform.position - patrol.target.position;
}
float sqrDistance = patrol.minDistance * patrol.minDistance;
if (targetOffset.sqrMagnitude <= sqrDistance)
{
flyOverTerrain.target = null;
lookAtCamera.target = null;
lingerDuration -= Time.deltaTime;
}
else
{
flyOverTerrain.target = patrol.target;
lookAtCamera.target = patrol.target;
}
distanceFromTarget = transform.position - patrol.target.position;
}
private int PingPong(int baseNumber, int limit)
{
if (limit < 2) return 0;
return limit - Mathf.Abs(limit - Modulus(baseNumber, limit + (limit - 2)) - 1) - 1;
}
private int Modulus(int baseNumber, int modulus)
{
return (modulus == 0) ? baseNumber : baseNumber - modulus * (int)Mathf.Floor(baseNumber / (float)modulus);
}
public void GeneratePatrolPoints()
{
patrolPoints = new PatrolData[TeleportationBooths.Count];
for (int i = 0; i < patrolPoints.Length; i++)
{
patrolPoints[i] = new PatrolData();
patrolPoints[i].target = TeleportationBooths[i].transform;
patrolPoints[i].minDistance = 30f;
patrolPoints[i].lingerDuration = 3f;
patrolPoints[i].desiredHeight = 20f;
patrolPoints[i].flightSmoothTime = 10f;
patrolPoints[i].maxFlightspeed = 10f;
patrolPoints[i].flightAcceleration = 3f;
patrolPoints[i].levelingSmoothTime = 0.5f;
patrolPoints[i].maxLevelingSpeed = 10000f;
patrolPoints[i].levelingAcceleration = 2f;
}
}
}
In this part inside the Update i'm comparing the old length of a list with the current length:
//Check if oldLength has changed
if (oldLength != TeleportationBooths.Count)
{
//Update oldLength
oldLength = TeleportationBooths.Count;
//Call your the function
GeneratePatrolPoints();
}
So in case i create a new objects without destroying the old ones first it will be fine the length is not the same and it will call GeneratePatrolPoints() and will update the targets with the new targets just added:
patrolPoints[i].target = TeleportationBooths[i].transform;
The problem is when i check the ui toggle and first destroy the objects and then create them again the length is the same as before so it will not call GeneratePatrolPoints() and will not update the targets.
So i'm getting missing object exception.
I'm updating the list but i also need to update the targets again.
In this script i decide if the create new objects and to add them to the list so the length will not be the same and everything is right or to destroy first the current objects and then create new ones but then the length will be the same:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GenerateObjectsButton : MonoBehaviour
{
[SerializeField]
private InstantiateObjects[] instantiateobjects;
private bool toggleOnOf;
public Toggle toggle;
private void Start()
{
toggle.onValueChanged.AddListener((value) =>
{
MyListener(value);
});
}
public void MyListener(bool value)
{
if (value)
{
//do the stuff when the toggle is on
toggleOnOf = true;
}
else
{
//do the stuff when the toggle is off
toggleOnOf = false;
}
}
public void OnButton()
{
for (int i = 0; i < instantiateobjects.Length; i++)
{
if (toggleOnOf == false)
{
instantiateobjects[i].generateObjectOnTerrain();
}
else
{
instantiateobjects[i].DestroyObjects();
instantiateobjects[i].generateObjectOnTerrain();
}
}
}
}
The problem is with the first script with comparing the length with the list count.
The solution is to add a new bool variable in the GenerateObjectsButton script:
public bool destroyed = false;
And set it to true after destroying and creating new objects again:
public void OnButton()
{
for (int i = 0; i < instantiateobjects.Length; i++)
{
if (toggleOnOf == false)
{
instantiateobjects[i].generateObjectOnTerrain();
}
else
{
instantiateobjects[i].DestroyObjects();
instantiateobjects[i].generateObjectOnTerrain();
destroyed = true;
}
}
}
Now destroyed is true.
Back to the PatrolOverTerrain script.
Now i'm not only checking if the length is not the same but also if destroyed is true:
//Check if oldLength has changed
if (oldLength != TeleportationBooths.Count)
{
//Update oldLength
oldLength = TeleportationBooths.Count;
//Call your the function
GeneratePatrolPoints();
}
GameObject go = GameObject.Find("Button");
var destroyed = go.GetComponent<GenerateObjectsButton>().destroyed;
if (destroyed)
{
GeneratePatrolPoints();
}
Now i know when i only created new objects and added them by comparing length or when first destroyed the objects and then created new so the length didn't change but the list it self did.
Anyway this is a working solution.

How to Detect Collision when a gameobject collide with a lineRender?

I want to draw some lines by dragging the mouse. I did that using this script .
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class DrawLine : MonoBehaviour
{
private LineRenderer line;
private bool isMousePressed;
private List<Vector3> pointsList;
private Vector3 mousePos;
// Structure for line points
struct myLine
{
public Vector3 StartPoint;
public Vector3 EndPoint;
};
// -----------------------------------
void Awake()
{
// Create line renderer component and set its property
line = gameObject.AddComponent<LineRenderer>();
line.material = new Material(Shader.Find("Particles/Additive"));
line.SetVertexCount(0);
line.SetWidth(0.1f,0.1f);
line.SetColors(Color.green, Color.green);
line.useWorldSpace = true;
isMousePressed = false;
pointsList = new List<Vector3>();
// renderer.material.SetTextureOffset(
}
// -----------------------------------
void Update ()
{
// If mouse button down, remove old line and set its color to green
if(Input.GetMouseButtonDown(0))
{
isMousePressed = true;
line.SetVertexCount(0);
//pointsList.RemoveRange(0,pointsList.Count);
line.SetColors(Color.green, Color.green);
}
else if(Input.GetMouseButtonUp(0))
{
isMousePressed = false;
}
// Drawing line when mouse is moving(presses)
if(isMousePressed)
{
mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z=0;
if (!pointsList.Contains (mousePos))
{
pointsList.Add (mousePos);
line.SetVertexCount (pointsList.Count);
line.SetPosition (pointsList.Count - 1, (Vector3)pointsList [pointsList.Count - 1]);
if(isLineCollide())
{
isMousePressed = false;
line.SetColors(Color.red, Color.red);
}
}
}
}
// -----------------------------------
// Following method checks is currentLine(line drawn by last two points) collided with line
// -----------------------------------
private bool isLineCollide()
{
// if (gameObject.tag == "default") {
if (pointsList.Count < 2)
return false;
int TotalLines = pointsList.Count - 1;
myLine[] lines = new myLine[TotalLines];
if (TotalLines > 1) {
for (int i = 0; i < TotalLines; i++) {
lines [i].StartPoint = (Vector3)pointsList [i];
lines [i].EndPoint = (Vector3)pointsList [i + 1];
}
}
for (int i = 0; i < TotalLines - 1; i++) {
myLine currentLine;
currentLine.StartPoint = (Vector3)pointsList [pointsList.Count - 2];
currentLine.EndPoint = (Vector3)pointsList [pointsList.Count - 1];
if (isLinesIntersect (lines [i], currentLine))
return true;
}
// }
return false;
}
// -----------------------------------
// Following method checks whether given two points are same or not
// -----------------------------------
private bool checkPoints (Vector3 pointA, Vector3 pointB)
{
return (pointA.x == pointB.x && pointA.y == pointB.y);
}
// -----------------------------------
// Following method checks whether given two line intersect or not
// -----------------------------------
private bool isLinesIntersect (myLine L1, myLine L2)
{
if (checkPoints (L1.StartPoint, L2.StartPoint) ||
checkPoints (L1.StartPoint, L2.EndPoint) ||
checkPoints (L1.EndPoint, L2.StartPoint) ||
checkPoints (L1.EndPoint, L2.EndPoint))
return false;
return((Mathf.Max (L1.StartPoint.x, L1.EndPoint.x) >= Mathf.Min (L2.StartPoint.x, L2.EndPoint.x)) &&
(Mathf.Max (L2.StartPoint.x, L2.EndPoint.x) >= Mathf.Min (L1.StartPoint.x, L1.EndPoint.x)) &&
(Mathf.Max (L1.StartPoint.y, L1.EndPoint.y) >= Mathf.Min (L2.StartPoint.y, L2.EndPoint.y)) &&
(Mathf.Max (L2.StartPoint.y, L2.EndPoint.y) >= Mathf.Min (L1.StartPoint.y, L1.EndPoint.y))
);
}
}
enter image description here
Now How to print something when my line collide with some gameobjects in the scene???
It means that when the line collide with my gameobject i want to say go to another scene.
You may use Raycast from LastPosition to CurrentPosition in Update method.
https://docs.unity3d.com/ScriptReference/Physics.Raycast.html
Example:
http://xenforo.unity3d.com/threads/general-purpose-method-for-better-collision-solving.64781/

Categories

Resources