提高inAreaRewardDefault。
整理Script位置。
This commit is contained in:
@@ -33,7 +33,7 @@ public class CommonParameterContainer : Singleton<CommonParameterContainer>
|
||||
[Tooltip("Enemy down in area Reward")]
|
||||
public float killTargetEnemyRewardDefault = 25f;
|
||||
[Tooltip("stay in firebasesArea reward")]
|
||||
public float inAreaRewardDefault = 12f;
|
||||
public float inAreaRewardDefault = 25.0f;
|
||||
[Tooltip("free left time bonus reward. ALLR + leftTime * r")]
|
||||
public float freeTimeBonusPerSec = 1.0f;
|
||||
[Tooltip("target left time bonus reward. ALLR + leftTime * r")]
|
||||
|
||||
@@ -0,0 +1,615 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
public class RewardFunction : MonoBehaviour
|
||||
{
|
||||
public enum EndType
|
||||
{ Win, Lose, Running, Num };
|
||||
|
||||
[SerializeField] private GameObject parameterContainerObj;
|
||||
[SerializeField] private GameObject sceneBlockContainerObj;
|
||||
[SerializeField] private GameObject targetControllerObj;
|
||||
[SerializeField] private GameObject environmentUIObj;
|
||||
[SerializeField] private GameObject enemyContainerObj;
|
||||
|
||||
private GameObject agentObj;
|
||||
private Camera fpsCam;
|
||||
private CommonParameterContainer commonParamCon;
|
||||
private SceneBlockContainer sceneBlockCon;
|
||||
private ParameterContainer paramCon;
|
||||
private TargetController targetCon;
|
||||
private EnvironmentUIControl envUICon;
|
||||
private AgentController agentCon;
|
||||
private RaySensors raySensors;
|
||||
|
||||
private bool firstRewardFlag = false;
|
||||
private float lastDistance;
|
||||
private float lastEnemyFacingDistance = 0f; // record last enemy facing minimum distance
|
||||
private float lastTargetFacingDistance = 0f; // record last target facing minimum distance
|
||||
private List<float> spinRecord = new List<float>();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
agentObj = gameObject;
|
||||
agentCon = agentObj.GetComponent<AgentController>();
|
||||
fpsCam = agentCon.fpsCam;
|
||||
commonParamCon = CommonParameterContainer.Instance;
|
||||
paramCon = parameterContainerObj.GetComponent<ParameterContainer>();
|
||||
sceneBlockCon = sceneBlockContainerObj.GetComponent<SceneBlockContainer>();
|
||||
targetCon = targetControllerObj.GetComponent<TargetController>();
|
||||
envUICon = environmentUIObj.GetComponent<EnvironmentUIControl>();
|
||||
raySensors = GetComponent<RaySensors>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the reward value.
|
||||
/// </summary>
|
||||
/// <param name="sceneReward">Reward value from the scene.</param>
|
||||
/// <param name="mouseX">Movement amount of the mouse along the X-axis.</param>
|
||||
/// <param name="movement">Movement of discrete.</param>
|
||||
/// <param name="shootState">State of the shooting action.</param>
|
||||
/// <returns>Returns the calculated total reward value.</returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the total reward based on the provided parameters,
|
||||
/// taking into account rewards for enemy kills, shooting actions, facing reward,
|
||||
/// and penalties such as spin and movement.
|
||||
/// </remarks>
|
||||
public float RewardCalculate(float sceneReward, float mouseX, float movement, int shootState)
|
||||
{
|
||||
float epreward = 0f;
|
||||
// Got kill point reward
|
||||
if (agentCon.enemyKillCount > 0)
|
||||
{
|
||||
for (int i = 0; i < agentCon.enemyKillCount; i++)
|
||||
{
|
||||
// get
|
||||
epreward += KillReward(agentCon.killEnemyPosition);
|
||||
}
|
||||
agentCon.enemyKillCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
agentCon.enemyKillCount = 0;
|
||||
}
|
||||
// Shoot action reward
|
||||
epreward += Ballistic(shootState) + sceneReward;
|
||||
// facing reward
|
||||
epreward += FacingReward();
|
||||
// Penalty
|
||||
// spin penalty
|
||||
spinRecord.Add(mouseX);
|
||||
if (spinRecord.Count >= commonParamCon.spinRecordMax)
|
||||
{
|
||||
spinRecord.RemoveAt(0);
|
||||
}
|
||||
float spinPenaltyReward = Math.Abs(spinRecord.ToArray().Sum() * commonParamCon.spinPenalty);
|
||||
if (spinPenaltyReward >= commonParamCon.spinPenaltyThreshold)
|
||||
{
|
||||
epreward -= spinPenaltyReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
epreward -= Math.Abs(mouseX) * commonParamCon.mousePenalty;
|
||||
}
|
||||
// move penalty
|
||||
if (movement != 0)
|
||||
{
|
||||
epreward -= commonParamCon.movePenalty;
|
||||
}
|
||||
return epreward;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the reward value for shooting actions.
|
||||
/// </summary>
|
||||
/// <param name="shootState">State value of the shooting action.</param>
|
||||
/// <returns>Returns the reward value associated with shooting.</returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the reward value based on the shooting state and other related conditions,
|
||||
/// such as whether the enemy was hit, whether the shot was towards the target area, and whether the gun was ready to shoot.
|
||||
/// </remarks>
|
||||
private float Ballistic(int shootState)
|
||||
{
|
||||
Vector3 point = new Vector3(fpsCam.pixelWidth / 2, fpsCam.pixelHeight / 2, 0);// start position
|
||||
Ray ray = fpsCam.ScreenPointToRay(point);
|
||||
RaycastHit hit;
|
||||
// Debug.DrawRay(centerRay.origin, centerRay.direction * 100, Color.blue);
|
||||
// Mouse Pressed
|
||||
if (shootState != 0 && agentCon.gunReadyToggle == true)
|
||||
{
|
||||
agentCon.lastShootTime = Time.time;
|
||||
if (Physics.Raycast(ray, out hit, 100))
|
||||
{
|
||||
if (hit.collider.tag != agentCon.myTag && hit.collider.tag != "Wall" && hit.collider.tag != "Untagged")
|
||||
{
|
||||
// kill enemy
|
||||
GameObject gotHitObj = hit.transform.gameObject;
|
||||
gotHitObj.GetComponent<States>().ReactToHit(commonParamCon.damage, gameObject);
|
||||
shootState = 0;
|
||||
return HitEnemyReward(gotHitObj.transform.position);
|
||||
}
|
||||
}
|
||||
if (targetCon.targetType == Targets.Attack)
|
||||
{
|
||||
// while if attack mode
|
||||
float targetDis = Vector3.Distance(sceneBlockCon.nowBlock.transform.position, transform.position);
|
||||
if (targetDis <= raySensors.viewDistance)
|
||||
{
|
||||
// Debug.DrawRay(new Vector3(0,0,0), viewPoint, Color.red);
|
||||
if (Vector3.Distance(ray.origin + (ray.direction * targetDis), sceneBlockCon.nowBlock.transform.position) <= sceneBlockCon.nowBlock.firebasesAreaDiameter / 2)
|
||||
{
|
||||
// im shooting at target but didn't hit enemy
|
||||
// Debug.DrawRay(centerRay.origin, viewPoint-centerRay.origin, Color.blue);
|
||||
return commonParamCon.shootTargetAreaReward;
|
||||
}
|
||||
}
|
||||
}
|
||||
shootState = 0;
|
||||
return commonParamCon.shootReward;
|
||||
}
|
||||
else if (shootState != 0 && agentCon.gunReadyToggle == false)
|
||||
{
|
||||
// shoot without ready
|
||||
shootState = 0;
|
||||
return commonParamCon.shootWithoutReadyReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// do not shoot
|
||||
shootState = 0;
|
||||
return commonParamCon.nonReward;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the reward value based on the character's facing direction.
|
||||
/// </summary>
|
||||
/// <returns>Returns the reward value for the facing direction.</returns>
|
||||
/// <remarks>
|
||||
/// This method calculates a reward value based on the relationship between the character's facing direction and the target.
|
||||
/// in free mode, if the character is facing an enemy, the reward is a fixed value
|
||||
/// in attack mode, the reward depends on the distance between the character and the target, among other factors.
|
||||
/// </remarks>
|
||||
private float FacingReward()
|
||||
{
|
||||
Vector3 screenCenter = new Vector3(fpsCam.pixelWidth / 2, fpsCam.pixelHeight / 2, 0);
|
||||
Vector3 screenLeft = new Vector3(0, fpsCam.pixelHeight / 2, 0);
|
||||
|
||||
Ray centerRay = fpsCam.ScreenPointToRay(screenCenter);
|
||||
Ray leftRay = fpsCam.ScreenPointToRay(screenLeft);
|
||||
|
||||
switch (targetCon.targetType)
|
||||
{
|
||||
case Targets.Free:
|
||||
return FacingRewardFree(centerRay);
|
||||
|
||||
case Targets.Attack:
|
||||
return FacingRewardAttack(centerRay, leftRay);
|
||||
|
||||
case Targets.Go:
|
||||
return FacingRewardGo(centerRay, leftRay);
|
||||
|
||||
case Targets.Stay:
|
||||
// stay mode has no facing reward
|
||||
return 0f;
|
||||
|
||||
default:
|
||||
Debug.LogError("Wrong target type");
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
private float FacingRewardFree(Ray centerRay)
|
||||
{
|
||||
float nowReward = 0;
|
||||
float enemyFacingDistance = 0f;
|
||||
bool isFacingtoEnemy = false;
|
||||
RaycastHit hit;
|
||||
if (Physics.Raycast(centerRay, out hit, 100))
|
||||
{
|
||||
// facing to an enemy
|
||||
if (hit.collider.tag != agentCon.myTag && hit.collider.tag != "Wall")
|
||||
{
|
||||
nowReward = commonParamCon.facingReward;
|
||||
isFacingtoEnemy = true;
|
||||
}
|
||||
}
|
||||
if (raySensors.inViewEnemies.Count > 0 && !isFacingtoEnemy)
|
||||
{
|
||||
// have enemy in view
|
||||
List<float> projectionDis = new List<float>();
|
||||
foreach (GameObject theEnemy in raySensors.inViewEnemies)
|
||||
{
|
||||
// for each enemy in view
|
||||
Vector3 projection = Vector3.Project(theEnemy.transform.position - transform.position, (centerRay.direction * 10));
|
||||
Vector3 verticalToRay = transform.position + projection - theEnemy.transform.position;
|
||||
projectionDis.Add(verticalToRay.magnitude);
|
||||
// Debug.Log("enemy!" + verticalToRay.magnitude);
|
||||
// Debug.DrawRay(transform.position, (centerRay.direction * 100), Color.cyan);
|
||||
// Debug.DrawRay(transform.position, theEnemy.transform.position - transform.position, Color.yellow);
|
||||
// Debug.DrawRay(transform.position, projection, Color.blue);
|
||||
// Debug.DrawRay(theEnemy.transform.position, verticalToRay, Color.magenta);
|
||||
}
|
||||
enemyFacingDistance = projectionDis.Min();
|
||||
if (enemyFacingDistance <= lastEnemyFacingDistance)
|
||||
{
|
||||
// closing to enemy
|
||||
nowReward = 1 / MathF.Sqrt(commonParamCon.facingInviewEnemyDisCOEF * enemyFacingDistance + 0.00001f);
|
||||
}
|
||||
else
|
||||
{
|
||||
nowReward = 0;
|
||||
}
|
||||
// enemy in view Reward
|
||||
lastEnemyFacingDistance = enemyFacingDistance;
|
||||
if (nowReward >= commonParamCon.facingReward) nowReward = commonParamCon.facingReward; // limit
|
||||
if (nowReward <= -commonParamCon.facingReward) nowReward = -commonParamCon.facingReward; // limit
|
||||
// Debug.Log("ninimum = " + nowReward);
|
||||
}
|
||||
return nowReward;
|
||||
}
|
||||
|
||||
private float FacingRewardGo(Ray centerRay, Ray leftRay)
|
||||
{
|
||||
float nowReward = 0;
|
||||
float camCenterToFireBase;
|
||||
float camCenterToViewEdge;
|
||||
(camCenterToFireBase, camCenterToViewEdge, _) = CameraCenterToFireBaseAndViewEdge(centerRay, leftRay);
|
||||
|
||||
// goto mode
|
||||
if (camCenterToFireBase <= camCenterToViewEdge)
|
||||
{
|
||||
// fireArea is in view
|
||||
nowReward = commonParamCon.facingReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
nowReward = 0;
|
||||
}
|
||||
return nowReward;
|
||||
}
|
||||
|
||||
private float FacingRewardAttack(Ray centerRay, Ray leftRay)
|
||||
{
|
||||
float nowReward = 0;
|
||||
float camCenterToFireBase;
|
||||
float targetDis;
|
||||
(camCenterToFireBase, _, targetDis) = CameraCenterToFireBaseAndViewEdge(centerRay, leftRay);
|
||||
// attack mode
|
||||
if (targetDis <= raySensors.viewDistance)
|
||||
{
|
||||
// Debug.DrawRay(new Vector3(0,0,0), viewPoint, Color.red);
|
||||
// while center of screen between target's distance is lower than firebasesAreaDiameter
|
||||
// while facing to target
|
||||
if (camCenterToFireBase <= sceneBlockCon.nowBlock.firebasesAreaDiameter / 2)
|
||||
{
|
||||
// Debug.DrawRay(centerRay.origin, viewPoint-centerRay.origin, Color.blue);
|
||||
nowReward = commonParamCon.facingReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// while not facing to target
|
||||
nowReward = (lastTargetFacingDistance - camCenterToFireBase) * commonParamCon.facingTargetReward;
|
||||
}
|
||||
}
|
||||
// update lastTargetFacingDistance
|
||||
lastTargetFacingDistance = camCenterToFireBase;
|
||||
return nowReward;
|
||||
}
|
||||
|
||||
private (float, float, float) CameraCenterToFireBaseAndViewEdge(Ray centerRay, Ray leftRay)
|
||||
{
|
||||
// target fireBaseArea Position, turen y to camera's y
|
||||
Vector3 fireBaseArea = sceneBlockCon.nowBlock.fireBasesAreaObj.transform.position;
|
||||
fireBaseArea.y = fpsCam.transform.position.y;
|
||||
|
||||
// my position, turn y to camera's y
|
||||
// Debug.DrawRay(fpsCam.transform.position, centerRay.direction * 100, Color.blue);
|
||||
Vector3 myposition = transform.position;
|
||||
myposition.y = fpsCam.transform.position.y;
|
||||
|
||||
// Target to Agent distance
|
||||
//Debug.DrawLine(fireBaseArea, myposition, Color.red);
|
||||
float targetDis = Vector3.Distance(fireBaseArea, myposition);
|
||||
|
||||
// point in centerRay and leftRay which distance is targetDis from camera center
|
||||
Vector3 pointInCenterRay = fpsCam.transform.position + (centerRay.direction * targetDis);
|
||||
Vector3 pointInLeftRay = fpsCam.transform.position + (leftRay.direction * targetDis);
|
||||
|
||||
// center of screen to target's distance
|
||||
// Debug.DrawLine(pointInCenterRay, fireBaseArea,Color.green);
|
||||
float camCenterToFireBase = Vector3.Distance(pointInCenterRay, fireBaseArea);
|
||||
|
||||
// left of screen to target's distance
|
||||
// Debug.DrawLine(pointInLeftRay, pointInCenterRay, Color.yellow);
|
||||
float camCenterToViewEdge = Vector3.Distance(pointInLeftRay, pointInCenterRay);
|
||||
return (camCenterToFireBase, camCenterToViewEdge, targetDis);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks the game's end state and retrieves rewards.
|
||||
/// </summary>
|
||||
/// <returns>A tuple containing the game's end type, current reward, and final reward.
|
||||
/// 1 = success,2 = overtime,0 = notover</returns>
|
||||
public (int, float, float) CheckOverAndRewards()
|
||||
{
|
||||
int endTypeInt = 0;
|
||||
float nowReward = 0;
|
||||
float endReward = 0;
|
||||
switch (targetCon.targetType)
|
||||
{
|
||||
case Targets.Go:
|
||||
// goto
|
||||
(endTypeInt, nowReward, endReward) = CheckOverAndRewardsGo();
|
||||
break;
|
||||
|
||||
case Targets.Attack:
|
||||
// attack
|
||||
(endTypeInt, nowReward, endReward) = CheckOverAndRewardsAttack();
|
||||
break;
|
||||
|
||||
case Targets.Defence:
|
||||
//defence
|
||||
(endTypeInt, nowReward, endReward) = CheckOverAndRewardsDefence();
|
||||
break;
|
||||
|
||||
case Targets.Stay:
|
||||
// Stay
|
||||
// endless
|
||||
nowReward = 0;
|
||||
endReward = 0;
|
||||
endTypeInt = (int)EndType.Running;
|
||||
break;
|
||||
|
||||
default:
|
||||
//free kill
|
||||
(endTypeInt, nowReward, endReward) = CheckOverAndRewardsFreeKill();
|
||||
break;
|
||||
}
|
||||
envUICon.ShowResult(endTypeInt);
|
||||
return (endTypeInt, nowReward, endReward);
|
||||
}
|
||||
|
||||
private (int, float, float) CheckOverAndRewardsGo()
|
||||
{
|
||||
int endTypeInt = 0;
|
||||
float nowReward = 0;
|
||||
float endReward = 0;
|
||||
float nowDistance = 0;
|
||||
|
||||
(nowDistance, targetCon.inArea) = sceneBlockCon.GetAgentTargetDistanceAndInside(agentObj.transform.position);
|
||||
envUICon.UpdateTargetGauge(sceneBlockCon.nowBlock.firebasesBelong, sceneBlockCon.nowBlock.belongMaxPoint);
|
||||
float areaTargetReward = GetDistanceReward(nowDistance, targetCon.inArea);
|
||||
//if(inArea != 0)
|
||||
if (sceneBlockCon.nowBlock.firebasesBelong >= sceneBlockCon.nowBlock.belongMaxPoint)
|
||||
{
|
||||
// win
|
||||
// let the area belongs to me
|
||||
nowReward = areaTargetReward;
|
||||
endReward = paramCon.goWinReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getDistanceReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Win;
|
||||
}
|
||||
else if (targetCon.leftTime <= 0)
|
||||
{
|
||||
// time out lose
|
||||
nowReward = areaTargetReward;
|
||||
endReward = commonParamCon.loseReward;
|
||||
endTypeInt = (int)EndType.Lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep on keeping on!
|
||||
nowReward = areaTargetReward;
|
||||
endReward = 0;
|
||||
endTypeInt = (int)EndType.Running;
|
||||
}
|
||||
return (endTypeInt, nowReward, endReward);
|
||||
}
|
||||
|
||||
private (int, float, float) CheckOverAndRewardsAttack()
|
||||
{
|
||||
int endTypeInt = 0;
|
||||
float nowReward = 0;
|
||||
float endReward = 0;
|
||||
float nowDistance = 0;
|
||||
(nowDistance, targetCon.inArea) = sceneBlockCon.GetAgentTargetDistanceAndInside(agentObj.transform.position);
|
||||
envUICon.UpdateTargetGauge(sceneBlockCon.nowBlock.firebasesBelong, sceneBlockCon.nowBlock.belongMaxPoint);
|
||||
if (sceneBlockCon.nowBlock.GetInAreaNumber(commonParamCon.group2Tag) <= 0 && targetCon.targetEnemySpawnFinish)
|
||||
{
|
||||
// win
|
||||
// let the area belongs to me and kill every enmy in this area.
|
||||
nowReward = 0;
|
||||
endReward = paramCon.attackWinReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getSceneReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Win;
|
||||
targetCon.targetEnemySpawnFinish = false;
|
||||
}
|
||||
else if (targetCon.leftTime <= 0 && targetCon.targetEnemySpawnFinish)
|
||||
{
|
||||
// time out lose
|
||||
nowReward = 0;
|
||||
endReward = commonParamCon.loseReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getSceneReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Lose;
|
||||
targetCon.targetEnemySpawnFinish = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep on keeping on!
|
||||
// nowReward = (paramCon.inAreaReward * inArea) + getDistanceReward(nowDistance);
|
||||
nowReward = 0;
|
||||
endReward = 0;
|
||||
targetCon.targetEnemySpawnFinish = true;
|
||||
endTypeInt = (int)EndType.Running;
|
||||
}
|
||||
return (endTypeInt, nowReward, endReward);
|
||||
}
|
||||
|
||||
private (int, float, float) CheckOverAndRewardsDefence()
|
||||
{
|
||||
// !!! NOT FINISHED YET!!!
|
||||
int endTypeInt = 0;
|
||||
float nowReward = 0;
|
||||
float endReward = 0;
|
||||
float nowDistance = 0;
|
||||
(nowDistance, targetCon.inArea) = sceneBlockCon.GetAgentTargetDistanceAndInside(agentObj.transform.position);
|
||||
envUICon.UpdateTargetGauge(sceneBlockCon.nowBlock.firebasesBelong, sceneBlockCon.nowBlock.belongMaxPoint);
|
||||
if (targetCon.leftTime <= 0 && sceneBlockCon.nowBlock.firebasesBelong >= 0f)
|
||||
{
|
||||
// win
|
||||
// time over and the area still mine
|
||||
nowReward = paramCon.defenceWinReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getSceneReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Win;
|
||||
}
|
||||
else if (sceneBlockCon.nowBlock.firebasesBelong <= sceneBlockCon.nowBlock.belongMaxPoint)
|
||||
{
|
||||
// lost area lose
|
||||
nowReward = commonParamCon.loseReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getSceneReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep on keeping on!
|
||||
// nowReward = (paramCon.inAreaReward * inArea) + getDistanceReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Running;
|
||||
}
|
||||
return (endTypeInt, nowReward, endReward);
|
||||
}
|
||||
|
||||
private (int, float, float) CheckOverAndRewardsFreeKill()
|
||||
{
|
||||
int endTypeInt = 0;
|
||||
float nowReward = 0;
|
||||
float endReward = 0;
|
||||
if (enemyContainerObj.transform.childCount <= 0)
|
||||
{
|
||||
// win
|
||||
// nowReward = paramCon.winReward + (paramCon.timeBonusPerSecReward * leftTime);
|
||||
nowReward = 0;
|
||||
endReward = paramCon.freeWinReward;
|
||||
endTypeInt = (int)EndType.Win;
|
||||
}
|
||||
else if (targetCon.leftTime <= 0)
|
||||
{
|
||||
// lose
|
||||
//nowReward = paramCon.loseReward;
|
||||
nowReward = 0;
|
||||
endReward = commonParamCon.loseReward;
|
||||
endTypeInt = (int)EndType.Lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep on keeping on!
|
||||
nowReward = 0;
|
||||
endReward = 0;
|
||||
endTypeInt = (int)EndType.Running;
|
||||
}
|
||||
return (endTypeInt, nowReward, endReward);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates scene reward based on distance, granting higher rewards for being closer to the target.
|
||||
/// </summary>
|
||||
/// <param name="nowDistance">The current distance.</param>
|
||||
/// <param name="inarea">Whether inside an area.</param>
|
||||
/// <returns>The reward value calculated based on distance.</returns>
|
||||
private float GetDistanceReward(float nowDistance, int inarea)
|
||||
{
|
||||
if (firstRewardFlag)
|
||||
{
|
||||
// first distance record
|
||||
(lastDistance, _) = sceneBlockCon.GetAgentTargetDistanceAndInside(agentObj.transform.position);
|
||||
firstRewardFlag = false;
|
||||
}
|
||||
float nowSeneReward = 0f;
|
||||
if (inarea != 0)
|
||||
{
|
||||
// in area
|
||||
nowSeneReward = paramCon.inAreaReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// out of area
|
||||
// nowSeneReward = paramCon.distanceReward * Math.Clamp(lastDistance - nowDistance, 0, 100);
|
||||
nowSeneReward = commonParamCon.distanceReward * (lastDistance - nowDistance);
|
||||
}
|
||||
lastDistance = nowDistance;
|
||||
return nowSeneReward;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates kill reward based on the position of the killed enemy.
|
||||
/// </summary>
|
||||
/// <param name="enemyPosition">The position of the killed enemy.</param>
|
||||
/// <returns>The reward value calculated based on the kill position.</returns>
|
||||
public float KillReward(Vector3 enemyPosition)
|
||||
{
|
||||
float nowKillReward = 0f;
|
||||
if (targetCon.targetType == Targets.Attack)
|
||||
{
|
||||
// attack mode
|
||||
(_, int isInArea) = sceneBlockCon.nowBlock.GetDistInArea(enemyPosition);
|
||||
if (isInArea == 1)
|
||||
{
|
||||
// kill in area enemy
|
||||
nowKillReward = paramCon.killTargetEnemyReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
nowKillReward = commonParamCon.killNonTargetReward;
|
||||
}
|
||||
}
|
||||
else if (targetCon.targetType == Targets.Free)
|
||||
{
|
||||
// free mode hit
|
||||
nowKillReward = paramCon.killTargetEnemyReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// goto & defence
|
||||
nowKillReward = commonParamCon.killNonTargetReward;
|
||||
}
|
||||
return nowKillReward;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates hit reward based on the position of the hit enemy and the current mode.
|
||||
/// </summary>
|
||||
/// <param name="enemyPosition">The position of the hit enemy.</param>
|
||||
/// <returns>The reward value calculated based on the hit position and mode.</returns>
|
||||
public float HitEnemyReward(Vector3 enemyPosition)
|
||||
{
|
||||
float nowHitReward = 0f;
|
||||
if (targetCon.targetType == Targets.Attack)
|
||||
{
|
||||
// attack mode
|
||||
(_, int isInArea) = sceneBlockCon.nowBlock.GetDistInArea(enemyPosition);
|
||||
if (isInArea == 1)
|
||||
{
|
||||
// hit in area enemy
|
||||
nowHitReward = paramCon.hitTargetReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// hit not in area enemy
|
||||
nowHitReward = commonParamCon.hitNonTargetReward;
|
||||
}
|
||||
}
|
||||
else if (targetCon.targetType == Targets.Free)
|
||||
{
|
||||
// free mode hit
|
||||
nowHitReward = paramCon.hitTargetReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// goto & defence
|
||||
nowHitReward = commonParamCon.hitNonTargetReward;
|
||||
}
|
||||
return nowHitReward;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04b45691af6143d4d84b5d024d062bf7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,151 @@
|
||||
using DG.Tweening; // Importing the DOTween library for smooth animations.
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems; // Using the EventSystem to handle UI interactions.
|
||||
|
||||
public class UIVisibilityController : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private GameObject targetUIObj;
|
||||
|
||||
[SerializeField]
|
||||
private GameObject triggerUIObj;
|
||||
|
||||
[SerializeField]
|
||||
private GameObject canvasObj;
|
||||
|
||||
[SerializeField]
|
||||
private Vector3 slideDirection = Vector3.zero;
|
||||
|
||||
[SerializeField]
|
||||
private Vector3 slideDistance = Vector3.zero;
|
||||
|
||||
[SerializeField]
|
||||
private float slideDuration = 0.2f;
|
||||
|
||||
// Cached positions and states for logic and animation.
|
||||
private Vector3 targetOriginalPosition;
|
||||
|
||||
private Vector3 triggerOriginalPosition;
|
||||
private Vector3 targetEndPosition;
|
||||
private Vector3 triggerEndPosition;
|
||||
private Vector3 originalCanvasPosition;
|
||||
private bool isInActive = true; // Indicates if the UI is currently inactive.
|
||||
private bool isOutActive = false; // Indicates if the UI is currently active.
|
||||
private bool isMouseInTarget = false; // Is the mouse currently over the target UI?
|
||||
private bool isMouseInTrigger = false; // Is the mouse currently over the trigger UI?
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Initial setup of component's states and values.
|
||||
InitializeCanvasPosition();
|
||||
InitializeSlideValues();
|
||||
InitializeEventTrigger();
|
||||
}
|
||||
|
||||
private void InitializeCanvasPosition()
|
||||
{
|
||||
if (canvasObj == null)
|
||||
{
|
||||
// Set canvasObj to the parent if not assigned.
|
||||
canvasObj = transform.parent.gameObject;
|
||||
}
|
||||
originalCanvasPosition = canvasObj.transform.position;
|
||||
}
|
||||
|
||||
private void InitializeSlideValues()
|
||||
{
|
||||
if (slideDirection == Vector3.zero)
|
||||
{
|
||||
// default slide direction is up (set to right).
|
||||
slideDirection = Vector3.right;
|
||||
Debug.LogError("SliderDirection not set, set default right");
|
||||
}
|
||||
if (slideDistance == Vector3.zero)
|
||||
{
|
||||
// default slide distance is based on targetUIObj dimensions.
|
||||
RectTransform targetRT = targetUIObj.GetComponent<RectTransform>();
|
||||
slideDistance = new Vector3(targetRT.rect.width, targetRT.rect.height, 0);
|
||||
}
|
||||
// Determine the start and end positions for sliding.
|
||||
targetOriginalPosition = targetUIObj.transform.position;
|
||||
triggerOriginalPosition = triggerUIObj.transform.position;
|
||||
targetEndPosition = targetOriginalPosition + Vector3.Scale(slideDirection, slideDistance);
|
||||
triggerEndPosition = triggerOriginalPosition + Vector3.Scale(slideDirection, slideDistance);
|
||||
}
|
||||
|
||||
private void InitializeEventTrigger()
|
||||
{
|
||||
// Setting up event triggers for mouse interactions.
|
||||
EventTrigger triggerObjET = triggerUIObj.GetComponent<EventTrigger>();
|
||||
if (triggerObjET == null)
|
||||
{
|
||||
triggerObjET = triggerUIObj.AddComponent<EventTrigger>();
|
||||
}
|
||||
EventTrigger targetObjET = targetUIObj.GetComponent<EventTrigger>();
|
||||
if (targetObjET == null)
|
||||
{
|
||||
targetObjET = targetUIObj.AddComponent<EventTrigger>();
|
||||
}
|
||||
triggerObjET.AddEventTrigger(EventTriggerType.PointerEnter, (eventData) => OnMouseIn(triggerUIObj));
|
||||
triggerObjET.AddEventTrigger(EventTriggerType.PointerExit, (eventData) => OnMouseOut(triggerUIObj));
|
||||
targetObjET.AddEventTrigger(EventTriggerType.PointerEnter, (eventData) => OnMouseIn(targetUIObj));
|
||||
targetObjET.AddEventTrigger(EventTriggerType.PointerExit, (eventData) => OnMouseOut(targetUIObj));
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// Check mouse interactions to determine whether to slide in or out the UI.
|
||||
if ((isMouseInTrigger || isMouseInTarget) && isInActive)
|
||||
{
|
||||
SlideInScreen();
|
||||
isInActive = false;
|
||||
isOutActive = true;
|
||||
}
|
||||
else if (!isMouseInTrigger && !isMouseInTarget && isOutActive)
|
||||
{
|
||||
SlideOutScreen();
|
||||
isInActive = true;
|
||||
isOutActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouseIn(GameObject type)
|
||||
{
|
||||
// Update flags based on which UI object the mouse enters.
|
||||
if (type == triggerUIObj)
|
||||
{
|
||||
isMouseInTrigger = true;
|
||||
}
|
||||
else if (type == targetUIObj)
|
||||
{
|
||||
isMouseInTarget = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouseOut(GameObject type)
|
||||
{
|
||||
// Update flags based on which UI object the mouse exits.
|
||||
if (type == triggerUIObj)
|
||||
{
|
||||
isMouseInTrigger = false;
|
||||
}
|
||||
else if (type == targetUIObj)
|
||||
{
|
||||
isMouseInTarget = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void SlideInScreen()
|
||||
{
|
||||
// Animate the UI objects to slide in.
|
||||
triggerUIObj.transform.DOMove(triggerEndPosition, slideDuration).SetEase(Ease.OutCirc).Play();
|
||||
targetUIObj.transform.DOMove(targetEndPosition, slideDuration).SetEase(Ease.OutCirc).Play();
|
||||
}
|
||||
|
||||
private void SlideOutScreen()
|
||||
{
|
||||
// Animate the UI objects to slide out.
|
||||
triggerUIObj.transform.DOMove(triggerOriginalPosition, slideDuration).SetEase(Ease.OutCirc).Play();
|
||||
targetUIObj.transform.DOMove(targetOriginalPosition, slideDuration).SetEase(Ease.OutCirc).Play();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b459fcafb205c9540a282b421abdf6d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user